/// <summary> /// This event is called when the vessel gone BOOM (the Vessel.Die() is called) /// If we have the update lock of it we kill it /// It doesn't matter if we own the control lock or not as perhaps we are killing a vessel of a player who disconnected. /// </summary> public void OnVesselWillDestroy(Vessel dyingVessel) { //Only send the vessel remove msg if we own the unloaded update lock if (!LockSystem.LockQuery.UnloadedUpdateLockExists(dyingVessel.id) || LockSystem.LockQuery.UnloadedUpdateLockBelongsToPlayer(dyingVessel.id, SettingsSystem.CurrentSettings.PlayerName) || dyingVessel.id == _recoveringTerminatingVesselId) { var ownVesselDying = FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == dyingVessel.id; var reason = dyingVessel.id == _recoveringTerminatingVesselId ? "Recovered/Terminated" : "Destroyed"; LunaLog.Log($"[LMP]: Removing vessel {dyingVessel.id}-{dyingVessel.persistentId}, Name: {dyingVessel.vesselName} from the server: {reason}"); if (!ownVesselDying) { //Add to the kill list so it's also removed from the store later on! System.KillVessel(dyingVessel.id, true, "OnVesselWillDestroy - " + reason); System.MessageSender.SendVesselRemove(dyingVessel); } else { //We do not add our OWN vessel to the kill list as then if we revert we won't be able to send the vessel proto again //As the "VesselWillBeKilled" method will return true. //For this reason we also tell the other players to NOT keep it in the remove list System.MessageSender.SendVesselRemove(dyingVessel, false); } //Vessel is dead so remove the locks. Do not remove the kerbal locks as that's done in the Kerbal system LockSystem.Singleton.ReleaseAllVesselLocks(null, dyingVessel.id, 0.5f); RemoveEvent.onLmpDestroyVessel.Fire(dyingVessel); VesselCommon.RemoveVesselFromSystems(dyingVessel.id); } }
/// <summary> /// Triggered when reverting back to the launchpad. The vessel id does NOT change /// </summary> public void OnRevertToLaunch() { if (FlightGlobals.ActiveVessel != null && !VesselCommon.IsSpectating) { LunaLog.Log("[LMP]: Detected a revert to launch!"); RemoveOldVesselAndItsDebris(FlightGlobals.ActiveVessel, ProtoCrewMember.RosterStatus.Assigned); System.MessageSender.SendVesselRemove(FlightGlobals.ActiveVessel, false); VesselCommon.RemoveVesselFromSystems(FlightGlobals.ActiveVessel.id); } }
/// <summary> /// Kills a vessel. /// </summary> public void KillVessel(Guid vesselId, bool addToKilledList, string reason) { VesselCommon.RemoveVesselFromSystems(vesselId); if (addToKilledList) { //Always add to the killed list even if it exists that vessel or not. RemovedVessels.TryAdd(vesselId, LunaNetworkTime.UtcNow); } KillVessel(FlightGlobals.fetch.LmpFindVessel(vesselId), reason); }
/// <summary> /// Triggered when reverting back to the editor. The vessel id DOES change /// </summary> public void OnRevertToEditor(EditorFacility data) { if (FlightGlobals.ActiveVessel != null && !VesselCommon.IsSpectating) { LunaLog.Log($"[LMP]: Detected a revert to editor! {data}"); RemoveOldVesselAndItsDebris(FlightGlobals.ActiveVessel, ProtoCrewMember.RosterStatus.Available); System.MessageSender.SendVesselRemove(FlightGlobals.ActiveVessel); //We consider this vessel removed but we let KSP do the remove of the vessel System.RemovedVessels.TryAdd(FlightGlobals.ActiveVessel.id, DateTime.Now); VesselCommon.RemoveVesselFromSystems(FlightGlobals.ActiveVessel.id); } }
/// <summary> /// If we get the Update lock, force the getting of the unloaded update lock. /// If we get a control lock, force getting the update and unloaded update /// </summary> public void LockAcquire(LockDefinition lockDefinition) { switch (lockDefinition.Type) { case LockType.Control: KscSceneSystem.Singleton.RefreshTrackingStationVessels(); if (lockDefinition.PlayerName == SettingsSystem.CurrentSettings.PlayerName) { VesselLockSystem.Singleton.StopSpectating(); LockSystem.Singleton.AcquireUpdateLock(lockDefinition.VesselId, true); LockSystem.Singleton.AcquireUnloadedUpdateLock(lockDefinition.VesselId, true); LockSystem.Singleton.AcquireKerbalLock(lockDefinition.VesselId, true); //As we got the lock of that vessel, remove its FS and position updates VesselCommon.RemoveVesselFromSystems(lockDefinition.VesselId); } else if (FlightGlobals.ActiveVessel && FlightGlobals.ActiveVessel.id == lockDefinition.VesselId) { System.StartSpectating(lockDefinition.VesselId); } break; case LockType.Update: if (lockDefinition.PlayerName != SettingsSystem.CurrentSettings.PlayerName) { return; } LockSystem.Singleton.AcquireUnloadedUpdateLock(lockDefinition.VesselId, true); LockSystem.Singleton.AcquireKerbalLock(lockDefinition.VesselId, true); //As we got the lock of that vessel, remove its FS and position updates VesselCommon.RemoveVesselFromSystems(lockDefinition.VesselId); break; case LockType.UnloadedUpdate: if (lockDefinition.PlayerName != SettingsSystem.CurrentSettings.PlayerName) { return; } //As we got the lock of that vessel, remove its FS and position updates VesselCommon.RemoveVesselFromSystems(lockDefinition.VesselId); break; } }
public void ExternalSeatBoard(Vessel vessel, Guid kerbalVesselId, string kerbalName) { //Do not check if we are spectating as we are perhaps boarding a seat of a vessel controlled by another player! if (vessel == null) { return; } LunaLog.Log("Crew-board to an external seat detected!"); VesselProtoSystem.Singleton.MessageSender.SendVesselMessage(vessel); VesselRemoveSystem.Singleton.MessageSender.SendVesselRemove(kerbalVesselId); VesselRemoveSystem.Singleton.KillVessel(kerbalVesselId, true, "Killing kerbal-vessel as it boarded a external seat"); LockSystem.Singleton.ReleaseAllVesselLocks(new[] { kerbalName }, kerbalVesselId); VesselCommon.RemoveVesselFromSystems(kerbalVesselId); }
private static void RemoveOldVesselAndItsDebris(Vessel vessel, ProtoCrewMember.RosterStatus kerbalStatus) { if (vessel == null) { return; } if (FlightGlobals.ActiveVessel.isEVA) { var kerbal = HighLogic.CurrentGame.CrewRoster[FlightGlobals.ActiveVessel.vesselName]; if (kerbal != null) { kerbal.rosterStatus = kerbalStatus; } System.KillVessel(FlightGlobals.ActiveVessel.id, true, "Revert. Active vessel is a kerbal"); System.MessageSender.SendVesselRemove(FlightGlobals.ActiveVessel); } //We detected a revert, now pick all the vessel parts (debris) that came from our main active //vessel and remove them both from our game and server var vesselsToRemove = FlightGlobals.Vessels .Where(v => v != null && v.rootPart && v.rootPart.missionID == vessel.rootPart.missionID && v.id != vessel.id).Distinct(); foreach (var vesselToRemove in vesselsToRemove) { if (vesselToRemove.isEVA) { var kerbal = HighLogic.CurrentGame.CrewRoster[vesselToRemove.vesselName]; if (kerbal != null) { kerbal.rosterStatus = kerbalStatus; } } System.MessageSender.SendVesselRemove(vesselToRemove); //We consider this vessel removed but we let KSP do the remove of the vessel System.RemovedVessels.TryAdd(vesselToRemove.id, DateTime.Now); VesselCommon.RemoveVesselFromSystems(vesselToRemove.id); } }
/// <summary> /// This event is called when vessel is terminated from track station /// </summary> public void OnVesselTerminated(ProtoVessel terminatedVessel) { if (!LockSystem.LockQuery.CanRecoverOrTerminateTheVessel(terminatedVessel.vesselID, SettingsSystem.CurrentSettings.PlayerName)) { LunaScreenMsg.PostScreenMessage(LocalizationContainer.ScreenText.CannotTerminate, 5f, ScreenMessageStyle.UPPER_CENTER); return; } _recoveringTerminatingVesselId = terminatedVessel.vesselID; LunaLog.Log($"[LMP]: Removing vessel {terminatedVessel.vesselID}, Name: {terminatedVessel.vesselName} from the server: Terminated"); System.MessageSender.SendVesselRemove(terminatedVessel.vesselID); //Vessel is terminated so remove locks Do not remove the kerbal locks as that's done in the Kerbal system LockSystem.Singleton.ReleaseAllVesselLocks(null, terminatedVessel.vesselID, 1); //We consider this vessel removed but we let KSP do the remove of the vessel System.RemovedVessels.TryAdd(terminatedVessel.vesselID, DateTime.Now); RemoveEvent.onLmpRecoveredVessel.Fire(terminatedVessel); VesselCommon.RemoveVesselFromSystems(terminatedVessel.vesselID); }
/// <summary> /// Kills a vessel. /// </summary> private void KillVessel(Vessel killVessel, string reason) { if (killVessel == null || killVessel.state == Vessel.State.DEAD) { return; } VesselCommon.RemoveVesselFromSystems(killVessel.id); LunaLog.Log($"[LMP]: Killing vessel {killVessel.id}. Reason: {reason}"); SwitchVesselIfKillingActiveVessel(killVessel); try { if (FlightGlobals.fetch.VesselTarget?.GetVessel().id == killVessel.id) { FlightGlobals.fetch.SetVesselTarget(null); } FlightGlobals.RemoveVessel(killVessel); foreach (var part in killVessel.parts) { Object.Destroy(part.gameObject); } Object.Destroy(killVessel.gameObject); HighLogic.CurrentGame.flightState.protoVessels.RemoveAll(v => v == null || v.vesselID == killVessel.id); if (KSCVesselMarkers.fetch) { KSCVesselMarkers.fetch.RefreshMarkers(); } } catch (Exception killException) { LunaLog.LogError($"[LMP]: Error destroying vessel: {killException}"); } }
/// <summary> /// If we get the Update lock, force the getting of the unloaded update lock. /// If we get a control lock, force getting the update and unloaded update /// </summary> public void LockAcquire(LockDefinition lockDefinition) { switch (lockDefinition.Type) { case LockType.Control: if (lockDefinition.PlayerName == SettingsSystem.CurrentSettings.PlayerName) { if (VesselCommon.IsSpectating) { VesselLockSystem.Singleton.StopSpectating(); } LockSystem.Singleton.AcquireUpdateLock(lockDefinition.VesselId, true); LockSystem.Singleton.AcquireUnloadedUpdateLock(lockDefinition.VesselId, true); LockSystem.Singleton.AcquireKerbalLock(lockDefinition.VesselId, true); //As we got the lock of that vessel, remove its FS and position updates //This is done so even if the vessel has queued updates, we ignore them as we are controlling it VesselCommon.RemoveVesselFromSystems(lockDefinition.VesselId); } else { //Somebody else got the control of our active vessel so start spectating if (FlightGlobals.ActiveVessel && FlightGlobals.ActiveVessel.id == lockDefinition.VesselId) { System.StartSpectating(lockDefinition.VesselId); } //If some other player got the control lock release the update lock in case we have it if (LockSystem.LockQuery.UpdateLockBelongsToPlayer(lockDefinition.VesselId, SettingsSystem.CurrentSettings.PlayerName)) { LockSystem.LockStore.RemoveLock(LockSystem.LockQuery.GetUpdateLock(lockDefinition.VesselId)); LockSystem.LockStore.AddOrUpdateLock(new LockDefinition(LockType.UnloadedUpdate, lockDefinition.PlayerName, lockDefinition.VesselId)); } //If some other player got the control lock release the unloaded update lock in case we have it if (LockSystem.LockQuery.UnloadedUpdateLockBelongsToPlayer(lockDefinition.VesselId, SettingsSystem.CurrentSettings.PlayerName)) { LockSystem.LockStore.RemoveLock(LockSystem.LockQuery.GetUnloadedUpdateLock(lockDefinition.VesselId)); LockSystem.LockStore.AddOrUpdateLock(new LockDefinition(LockType.UnloadedUpdate, lockDefinition.PlayerName, lockDefinition.VesselId)); } //TODO:We should release the kerbals locks? } break; case LockType.Update: if (lockDefinition.PlayerName != SettingsSystem.CurrentSettings.PlayerName) { //If some other player got the update lock release the unloaded update lock just in case we have it if (LockSystem.LockQuery.UnloadedUpdateLockBelongsToPlayer(lockDefinition.VesselId, SettingsSystem.CurrentSettings.PlayerName)) { LockSystem.LockStore.RemoveLock(LockSystem.LockQuery.GetUnloadedUpdateLock(lockDefinition.VesselId)); LockSystem.LockStore.AddOrUpdateLock(new LockDefinition(LockType.UnloadedUpdate, lockDefinition.PlayerName, lockDefinition.VesselId)); } //TODO:We should release the kerbals locks? } else { LockSystem.Singleton.AcquireUnloadedUpdateLock(lockDefinition.VesselId, true); LockSystem.Singleton.AcquireKerbalLock(lockDefinition.VesselId, true); } break; } }
/// <summary> /// Kills a vessel. /// </summary> public void KillVessel(Guid vesselId, string reason) { VesselCommon.RemoveVesselFromSystems(vesselId); KillVessel(FlightGlobals.fetch.LmpFindVessel(vesselId), reason); }