/// <summary> /// Check vessels that must be loaded /// </summary> private void CheckVesselsToLoad() { try { if (ProtoSystemBasicReady && !VesselCommon.ActiveVesselIsInSafetyBubble()) { //Load vessels that don't exist, are in our subspace and out of safety bubble var vesselsToLoad = VesselsProtoStore.AllPlayerVessels .Where(v => !v.Value.VesselExist && v.Value.ShouldBeLoaded && !v.Value.IsInSafetyBubble); foreach (var vesselProto in vesselsToLoad) { if (VesselRemoveSystem.VesselWillBeKilled(vesselProto.Key)) { continue; } LunaLog.Log($"[LMP]: Loading vessel {vesselProto.Key}"); CurrentlyUpdatingVesselId = vesselProto.Key; if (VesselLoader.LoadVessel(vesselProto.Value.ProtoVessel)) { LunaLog.Log($"[LMP]: Vessel {vesselProto.Key} loaded"); } CurrentlyUpdatingVesselId = Guid.Empty; } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in CheckVesselsToLoad {e}"); } }
/// <summary> /// Send the definition of our own vessel and the secondary vessels. We only send them after an interval specified. /// If the other player vessels are far we don't send them very often. /// </summary> private void SendVesselDefinition() { try { if (ProtoSystemReady) { if (!VesselCommon.ActiveVesselIsInSafetyBubble()) { MessageSender.SendVesselMessage(FlightGlobals.ActiveVessel); } foreach (var vessel in VesselCommon.GetSecondaryVessels()) { MessageSender.SendVesselMessage(vessel); } ChangeRoutineExecutionInterval("SendVesselDefinition", VesselCommon.PlayerVesselsNearby() ? SettingsSystem.ServerSettings.VesselDefinitionSendMsInterval : SettingsSystem.ServerSettings.VesselDefinitionSendFarMsInterval); } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in SendVesselDefinition {e}"); } }
/// <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)); } } } }
/// <summary> /// Check vessels that must be reloaded /// </summary> private void CheckVesselsToReload() { try { if (ProtoSystemBasicReady && !VesselCommon.ActiveVesselIsInSafetyBubble()) { //Reload vessels that exist var vesselsToReLoad = AllPlayerVessels .Where(pv => !pv.Value.Loaded && pv.Value.VesselExist) .ToArray(); foreach (var vesselProto in vesselsToReLoad) { if (SystemsContainer.Get <VesselRemoveSystem>().VesselWillBeKilled(vesselProto.Key)) { continue; } LunaLog.Log($"[LMP]: Reloading vessel {vesselProto.Key}"); if (VesselLoader.ReloadVessel(vesselProto.Value.ProtoVessel)) { vesselProto.Value.Loaded = true; LunaLog.Log($"[LMP]: Vessel {vesselProto.Key} reloaded"); UpdateVesselProtoInDictionary(vesselProto.Value); } } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in CheckVesselsToReload {e}"); } }
/// <summary> /// Check vessels that must be loaded /// </summary> private void CheckVesselsToLoad() { try { if (ProtoSystemBasicReady && !VesselCommon.ActiveVesselIsInSafetyBubble()) { //Load vessels that don't exist and are in our subspace var vesselsToLoad = AllPlayerVessels .Where(v => !v.Value.Loaded && !v.Value.VesselExist && (SettingsSystem.ServerSettings.ShowVesselsInThePast || !VesselCommon.VesselIsControlledAndInPastSubspace(v.Value.VesselId))) .ToArray(); foreach (var vesselProto in vesselsToLoad) { if (SystemsContainer.Get <VesselRemoveSystem>().VesselWillBeKilled(vesselProto.Key)) { continue; } LunaLog.Log($"[LMP]: Loading vessel {vesselProto.Key}"); if (VesselLoader.LoadVessel(vesselProto.Value.ProtoVessel)) { vesselProto.Value.Loaded = true; LunaLog.Log($"[LMP]: Vessel {vesselProto.Key} loaded"); UpdateVesselProtoInDictionary(vesselProto.Value); } } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in CheckVesselsToLoad {e}"); } }
/// <summary> /// Triggered when a part that is in our vessel is about to die /// </summary> /// <param name="data"></param> public void OnPartDie(Part data) { if (!VesselCommon.IsSpectating && !VesselCommon.ActiveVesselIsInSafetyBubble() && data.vessel.id == FlightGlobals.ActiveVessel.id) { var msgData = new VesselChangeMsgData { ChangeType = (int)VesselChangeType.EXPLODE, PartCraftId = data.craftID, PartFlightId = data.flightID, VesselId = data.vessel.id }; System.MessageSender.SendMessage(msgData); } }
/// <summary> /// Check vessels that must be loaded /// </summary> private void CheckVesselsToLoad() { try { if (ProtoSystemBasicReady) { //Load vessels that don't exist, are in our subspace and out of safety bubble var vesselsToLoad = VesselsProtoStore.AllPlayerVessels.Where(v => !v.Value.VesselExist && v.Value.ShouldBeLoaded); foreach (var vesselProto in vesselsToLoad) { if (VesselRemoveSystem.VesselWillBeKilled(vesselProto.Key)) { continue; } //Only load vessels that are in safety bubble on the track station if (vesselProto.Value.IsInSafetyBubble && HighLogic.LoadedScene != GameScenes.TRACKSTATION) { continue; } if (VesselCommon.ActiveVesselIsInSafetyBubble() && VesselCommon.IsNearKsc(vesselProto.Value.ProtoVessel, 20000)) { continue; } LunaLog.Log($"[LMP]: Loading vessel {vesselProto.Key}"); CurrentlyUpdatingVesselId = vesselProto.Key; if (VesselLoader.LoadVessel(vesselProto.Value.ProtoVessel)) { LunaLog.Log($"[LMP]: Vessel {vesselProto.Key} loaded"); } CurrentlyUpdatingVesselId = Guid.Empty; } } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in CheckVesselsToLoad {e}"); } }
/// <summary> /// Send the definition of our own vessel and the secondary vessels. We only send them after an interval specified. /// If the other player vessels are far we don't send them very often. /// </summary> private IEnumerator SendVesselDefinition() { var seconds = new WaitForSeconds(VesselDefinitionSendSInterval); var secondsFar = new WaitForSeconds(VesselDefinitionSendFarSInterval); while (true) { try { if (!Enabled) { break; } if (ProtoSystemReady) { if (!VesselCommon.ActiveVesselIsInSafetyBubble()) { MessageSender.SendVesselMessage(FlightGlobals.ActiveVessel); } foreach (var vessel in VesselCommon.GetSecondaryVessels()) { MessageSender.SendVesselMessage(vessel); } } } catch (Exception e) { Debug.LogError($"[LMP]: Coroutine error in SendVesselDefinition {e}"); } if (VesselCommon.PlayerVesselsNearby()) { yield return(seconds); } else { yield return(secondsFar); } } }
private static string GetCurrentShipStatus() { var bodyName = VesselCommon.ActiveVesselIsInSafetyBubble() ? "safety bubble" : FlightGlobals.ActiveVessel.mainBody.bodyName; switch (FlightGlobals.ActiveVessel.situation) { case Vessel.Situations.DOCKED: return("Docked above " + bodyName); case Vessel.Situations.ESCAPING: if (FlightGlobals.ActiveVessel.orbit.timeToPe < 0) { return("Escaping " + bodyName); } return("Encountering " + bodyName); case Vessel.Situations.FLYING: return("Flying above " + bodyName); case Vessel.Situations.LANDED: return("Landed on " + bodyName); case Vessel.Situations.ORBITING: return("Orbiting " + bodyName); case Vessel.Situations.PRELAUNCH: return("Launching from " + bodyName); case Vessel.Situations.SPLASHED: return("Splashed on " + bodyName); case Vessel.Situations.SUB_ORBITAL: if (FlightGlobals.ActiveVessel.verticalSpeed > 0) { return("Ascending from " + bodyName); } return("Descending to " + bodyName); default: return("Error"); } }
/// <summary> /// Check vessels that must be reloaded /// </summary> private void CheckVesselsToRefresh() { try { if ((DateTime.UtcNow - LastReloadCheck).TotalMilliseconds > 1500 && ProtoSystemBasicReady && !VesselCommon.ActiveVesselIsInSafetyBubble()) { VesselsToRefresh.Clear(); //We get the vessels that already exist VesselsToRefresh.AddRange(VesselsProtoStore.AllPlayerVessels .Where(pv => pv.Value.VesselExist && pv.Value.VesselHasUpdate) .Select(v => v.Key)); //Do not iterate directly trough the AllPlayerVessels dictionary as the collection can be modified in another threads! foreach (var vesselIdToReload in VesselsToRefresh) { if (VesselRemoveSystem.VesselWillBeKilled(vesselIdToReload)) { continue; } //Do not handle vessel proto updates over our OWN active vessel if we are not spectating //If there is an undetected dock (our protovessel has been modified) it will be detected //in the docksystem if (vesselIdToReload == FlightGlobals.ActiveVessel?.id && !VesselCommon.IsSpectating) { continue; } if (VesselsProtoStore.AllPlayerVessels.TryGetValue(vesselIdToReload, out var vesselProtoUpdate)) { CurrentlyUpdatingVesselId = vesselIdToReload; ProtoToVesselRefresh.UpdateVesselPartsFromProtoVessel(vesselProtoUpdate.Vessel, vesselProtoUpdate.ProtoVessel, vesselProtoUpdate.VesselParts.Keys); vesselProtoUpdate.VesselHasUpdate = false; CurrentlyUpdatingVesselId = Guid.Empty; } } LastReloadCheck = DateTime.UtcNow; } } catch (Exception e) { LunaLog.LogError($"[LMP]: Error in CheckVesselsToReload {e}"); } }