/// <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);
            }
        }
Beispiel #5
0
        /// <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;
            }
        }
Beispiel #6
0
        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);
 }