Example #1
0
        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);
        }
Example #2
0
        /// <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>
        /// Event triggered when a vessel undocks
        /// </summary>
        /// <param name="part"></param>
        public void OnPartUndock(Part part)
        {
            var vessel = part.vessel;

            if (vessel == null)
            {
                return;
            }

            var isEvaPart = part.FindModuleImplementing <KerbalEVA>() != null;

            if (isEvaPart) //This is the case when a kerbal gets out of a external command seat
            {
                vessel.parts.Remove(part);
                VesselProtoSystem.Singleton.MessageSender.SendVesselMessage(vessel, true);
            }

            //Update the vessel in the proto store as it will have now less parts.
            //If we don't do this it may be reloaded.
            VesselsProtoStore.AddOrUpdateVesselToDictionary(vessel);

            if (VesselCommon.IsSpectating)
            {
                FlightCamera.SetTarget(part.vessel);
                part.vessel.MakeActive();
            }
        }
 private static void HandleVesselProto(VesselProtoMsgData messageData)
 {
     if (!VesselRemoveSystem.Singleton.VesselWillBeKilled(messageData.Vessel.VesselId) && messageData.Vessel.VesselId != Guid.Empty)
     {
         VesselsProtoStore.HandleVesselProtoData(messageData.Vessel.Data, messageData.Vessel.NumBytes, messageData.Vessel.VesselId);
     }
 }
Example #5
0
        /// <summary>
        /// Event called when a part is dead and removed from the game
        /// </summary>
        public void OnPartDie(Part data)
        {
            if (VesselCommon.IsSpectating || data.vessel == null)
            {
                return;
            }
            if (data.vessel.id != VesselProtoSystem.CurrentlyUpdatingVesselId && !VesselRemoveSystem.Singleton.VesselWillBeKilled(data.vessel.id))
            {
                if (VesselsProtoStore.AllPlayerVessels.ContainsKey(data.vessel.id))
                {
                    if (!LockSystem.LockQuery.UpdateLockBelongsToPlayer(data.vessel.id, SettingsSystem.CurrentSettings.PlayerName))
                    {
                        VesselsProtoStore.AllPlayerVessels[data.vessel.id].VesselHasUpdate = true;
                    }
                }
                else
                {
                    //The vessel is NEW as it's not in the store. It might be a debris...
                    var rootPartOrFirstPart = data.vessel.rootPart ?? data.vessel.parts.FirstOrDefault();
                    if (rootPartOrFirstPart != null)
                    {
                        var originalVessel = VesselsProtoStore.GetVesselByPartId(rootPartOrFirstPart.flightID);
                        if (originalVessel == null)
                        {
                            return;
                        }

                        if (!LockSystem.LockQuery.UpdateLockBelongsToPlayer(originalVessel.id, SettingsSystem.CurrentSettings.PlayerName))
                        {
                            VesselsProtoStore.AllPlayerVessels[originalVessel.id].VesselHasUpdate = true;
                        }
                    }
                }
            }
        }
        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();
            }
        }
Example #7
0
 private static void HandleVesselProto(VesselProtoMsgData messageData)
 {
     if (!SystemsContainer.Get <VesselRemoveSystem>().VesselWillBeKilled(messageData.Vessel.VesselId) && messageData.Vessel.VesselId != Guid.Empty)
     {
         VesselsProtoStore.HandleVesselProtoData(messageData.Vessel.Data, messageData.Vessel.NumBytes, messageData.Vessel.VesselId);
     }
 }
Example #8
0
        public void SendVesselMessage(Vessel vessel, bool forceSend, bool forceReloadOnReceive)
        {
            if (vessel == null || (!forceSend && VesselCommon.IsSpectating) || vessel.state == Vessel.State.DEAD || VesselRemoveSystem.Singleton.VesselWillBeKilled(vessel.id))
            {
                return;
            }

            if (!forceSend && !LockSystem.LockQuery.UnloadedUpdateLockBelongsToPlayer(vessel.id, SettingsSystem.CurrentSettings.PlayerName))
            {
                return;
            }
            if (!forceSend && !LockSystem.LockQuery.UpdateLockBelongsToPlayer(vessel.id, SettingsSystem.CurrentSettings.PlayerName))
            {
                return;
            }

            var vesselHasChanges = VesselToProtoRefresh.RefreshVesselProto(vessel);

            if (forceSend || vesselHasChanges || !VesselsProtoStore.AllPlayerVessels.ContainsKey(vessel.id))
            {
                SendVesselMessage(vessel.BackupVessel(), forceReloadOnReceive);
            }

            if (!VesselsProtoStore.AllPlayerVessels.ContainsKey(vessel.id))
            {
                VesselsProtoStore.AddOrUpdateVesselToDictionary(vessel);
            }
        }
Example #9
0
        /// <summary>
        /// This method prepares the protovessel class and send the message, it's intended to be run in another thread
        /// </summary>
        private void PrepareAndSendProtoVessel(ProtoVessel protoVessel)
        {
            //Never send empty vessel id's (it happens with flags...)
            if (protoVessel.vesselID == Guid.Empty || protoVessel.vesselName == null)
            {
                return;
            }

            //VesselSerializedBytes is shared so lock it!
            lock (VesselArraySyncLock)
            {
                VesselSerializer.SerializeVesselToArray(protoVessel, VesselSerializedBytes, out var numBytes);
                if (numBytes > 0)
                {
                    VesselsProtoStore.RawUpdateVesselProtoData(VesselSerializedBytes, numBytes, protoVessel.vesselID);

                    var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselProtoMsgData>();
                    FillAndSendProtoMessageData(protoVessel.vesselID, msgData, VesselSerializedBytes, numBytes);
                }
                else
                {
                    if (protoVessel.vesselType == VesselType.Debris)
                    {
                        LunaLog.Log($"Serialization of debris vessel: {protoVessel.vesselID} name: {protoVessel.vesselName} failed. Adding to kill list");
                        SystemsContainer.Get <VesselRemoveSystem>().AddToKillList(protoVessel.vesselID);
                    }
                }
            }
        }
Example #10
0
        public void SendVesselUpdate(Vessel vessel)
        {
            var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselUpdateMsgData>();

            msgData.VesselId        = vessel.id;
            msgData.Name            = vessel.vesselName;
            msgData.Type            = vessel.vesselType.ToString();
            msgData.Situation       = vessel.situation.ToString();
            msgData.Landed          = vessel.Landed;
            msgData.LandedAt        = vessel.landedAtLast;
            msgData.DisplayLandedAt = vessel.displaylandedAt;
            msgData.Splashed        = vessel.Splashed;
            msgData.MissionTime     = vessel.missionTime;
            msgData.LaunchTime      = vessel.launchTime;
            msgData.LastUt          = vessel.lastUT;
            msgData.Persistent      = vessel.isPersistent;
            msgData.RefTransformId  = vessel.referenceTransformId;

            for (var i = 0; i < 17; i++)
            {
                if (msgData.ActionGroups[i] == null)
                {
                    msgData.ActionGroups[i] = new ActionGroup();
                }

                msgData.ActionGroups[i].ActionGroupName = ((KSPActionGroup)(1 << (i & 31))).ToString();
                msgData.ActionGroups[i].State           = vessel.ActionGroups.groups[i];
                msgData.ActionGroups[i].Time            = vessel.ActionGroups.cooldownTimes[i];
            }

            //Update our own values in the store aswell as otherwise if we leave the vessel it can still be in the safety bubble
            VesselsProtoStore.UpdateVesselProtoValues(msgData);

            SendMessage(msgData);
        }
Example #11
0
        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
            }
        }
Example #12
0
        /// <summary>
        /// Called when a vessel is initiated.
        /// </summary>
        public void VesselCreate(Vessel data)
        {
            //We are just reloading a vessel and the vessel.Load() was triggered so we should not do anything!
            if (data.id == VesselLoader.ReloadingVesselId)
            {
                return;
            }

            //No need to check the unloaded update locks as vessels when unloaded don't have parts!
            if (!VesselCommon.IsSpectating && data.id != VesselProtoSystem.CurrentlyUpdatingVesselId && !VesselRemoveSystem.Singleton.VesselWillBeKilled(data.id))
            {
                //We are modifying a vessel that LMP is not handling
                if (VesselsProtoStore.AllPlayerVessels.ContainsKey(data.id))
                {
                    //The vessel even exists on the store so probably it's a vessel that has lost a part or smth like that...
                    if (LockSystem.LockQuery.UpdateLockBelongsToPlayer(data.id, SettingsSystem.CurrentSettings.PlayerName))
                    {
                        //We own the update lock of that vessel that suffered a modification so just leave it here
                        //The main system has a routine that will check changes and send the new definition
                        LunaLog.Log($"SKIPPING detected change in vesselId {data.id} name {data.vesselName} (we own update lock)");
                    }
                    else
                    {
                        LunaLog.Log($"REVERTING change in NEW vesselId {data.id} name {data.vesselName} (DON'T own UnloadedUpdate lock)");
                        VesselsProtoStore.AllPlayerVessels[data.id].VesselHasUpdate = true;
                    }
                }
                else
                {
                    //The vessel is NEW as it's not in the store. It might be a debris...
                    var rootPartOrFirstPart = data.rootPart ?? data.parts.FirstOrDefault();
                    if (rootPartOrFirstPart != null)
                    {
                        var originalVessel = VesselsProtoStore.GetVesselByPartId(rootPartOrFirstPart.flightID);
                        if (originalVessel == null)
                        {
                            //We didn't find an original vessel so it's probably a totally new vessel that was spawned...
                            return;
                        }

                        //The vessel even exists on the store so probably it's a vessel that has lost a part or smth like that...
                        if (LockSystem.LockQuery.UpdateLockBelongsToPlayer(originalVessel.id, SettingsSystem.CurrentSettings.PlayerName))
                        {
                            LunaLog.Log($"SENDING NEW vesselId {data.id} name {data.vesselName} (Original vessel UPD lock is ours)");

                            //We own the update lock of that vessel that originated that part so let's get that update lock as forced
                            //and send the definition with the main system routine
                            LockSystem.Singleton.AcquireUpdateLock(data.id, true);
                        }
                        else
                        {
                            LunaLog.Log($"REVERTING NEW vesselId {data.id} name {data.vesselName} (UPD lock is NOT ours)");
                            VesselRemoveSystem.Singleton.AddToKillList(data.id);
                        }
                    }
                }
            }
        }
        public void SendVesselUpdate(Vessel vessel)
        {
            if (vessel == null)
            {
                return;
            }

            var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselUpdateMsgData>();

            msgData.GameTime         = TimeSyncerSystem.UniversalTime;
            msgData.VesselId         = vessel.id;
            msgData.Name             = vessel.vesselName;
            msgData.Type             = vessel.vesselType.ToString();
            msgData.DistanceTraveled = vessel.distanceTraveled;

            msgData.Situation       = vessel.situation.ToString();
            msgData.Landed          = vessel.Landed;
            msgData.LandedAt        = vessel.landedAt;
            msgData.DisplayLandedAt = vessel.displaylandedAt;
            msgData.Splashed        = vessel.Splashed;
            msgData.MissionTime     = vessel.missionTime;
            msgData.LaunchTime      = vessel.launchTime;
            msgData.LastUt          = vessel.lastUT;
            msgData.Persistent      = vessel.isPersistent;
            msgData.RefTransformId  = vessel.referenceTransformId;

            msgData.AutoClean       = vessel.AutoClean;
            msgData.AutoCleanReason = vessel.AutoCleanReason;
            msgData.WasControllable = vessel.IsControllable;
            msgData.Stage           = vessel.currentStage;
            msgData.Com[0]          = vessel.localCoM.x;
            msgData.Com[1]          = vessel.localCoM.y;
            msgData.Com[2]          = vessel.localCoM.z;

            vessel.protoVessel.autoClean       = vessel.AutoClean;
            vessel.protoVessel.autoCleanReason = vessel.AutoCleanReason;
            vessel.protoVessel.wasControllable = vessel.IsControllable;
            vessel.protoVessel.CoM             = vessel.localCoM;
            vessel.protoVessel.stage           = vessel.currentStage;

            for (var i = 0; i < 17; i++)
            {
                if (msgData.ActionGroups[i] == null)
                {
                    msgData.ActionGroups[i] = new ActionGroup();
                }

                msgData.ActionGroups[i].ActionGroupName = ((KSPActionGroup)(1 << (i & 31))).ToString();
                msgData.ActionGroups[i].State           = vessel.ActionGroups.groups[i];
                msgData.ActionGroups[i].Time            = vessel.ActionGroups.cooldownTimes[i];
            }

            //Update our own values in the store aswell as otherwise if we leave the vessel it can still be in the safety bubble
            VesselsProtoStore.UpdateVesselProtoValues(msgData);
            UpdateOwnProtoVesselValues(vessel);

            SendMessage(msgData);
        }
Example #14
0
        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);
        }
        /// <summary>
        /// Called when a vessel is initiated.
        /// </summary>
        public void VesselCreate(Vessel data)
        {
            //We just created a vessel that exists in the store so we can just ignore this
            if (VesselsProtoStore.AllPlayerVessels.ContainsKey(data.id))
            {
                return;
            }

            //This happens when vessel crashes
            if (string.IsNullOrEmpty(data.vesselName))
            {
                return;
            }

            //We are reloading a vessel so we can ignore this
            if (VesselLoader.ReloadingVesselId == data.id)
            {
                return;
            }

            //The vessel is NEW as it's not in the store. It might be a debris...
            var rootPartOrFirstPartFlightId = data.rootPart?.flightID ?? data.parts.FirstOrDefault()?.flightID ?? data.protoVessel?.protoPartSnapshots?.FirstOrDefault()?.flightID ?? 0;

            if (rootPartOrFirstPartFlightId != 0)
            {
                var originalVessel = VesselsProtoStore.GetVesselByPartId(rootPartOrFirstPartFlightId);
                if (originalVessel == null)
                {
                    //We didn't find an original vessel so it's probably a totally new vessel that spawned...
                    LunaLog.Log($"SENDING NEW vesselId {data.id} name {data.vesselName} (Original vessel NOT found)");

                    System.MessageSender.SendVesselMessage(data, true, false);
                    LockSystem.Singleton.AcquireUpdateLock(data.id, true);
                }
                else
                {
                    //The vessel even exists on the store so probably it's a vessel that has lost a part or smth like that...
                    if (LockSystem.LockQuery.UpdateLockBelongsToPlayer(originalVessel.id, SettingsSystem.CurrentSettings.PlayerName))
                    {
                        //We own the update lock of that vessel that originated that part so let's get that update lock as forced and send the definition
                        LunaLog.Log($"SENDING NEW vesselId {data.id} name {data.vesselName} (Original vessel UPD lock is ours)");

                        System.MessageSender.SendVesselMessage(data, true, false);
                        LockSystem.Singleton.AcquireUpdateLock(data.id, true);
                    }
                    else
                    {
                        LunaLog.Log($"REVERTING NEW vesselId {data.id} name {data.vesselName} (UPD lock is NOT ours)");
                        VesselRemoveSystem.Singleton.AddToKillList(data.id, "Tried to create a new vessel when the update lock is not ours");
                    }
                }
            }
        }
Example #16
0
        /// <summary>
        /// Call this method to apply a vessel update using interpolation
        /// </summary>
        public void ApplyInterpolatedVesselUpdate()
        {
            if (Body == null)
            {
                return;
            }

            if (InterpolationFinished && VesselPositionSystem.TargetVesselUpdateQueue.TryGetValue(VesselId, out var queue) && queue.TryDequeue(out var targetUpdate))
            {
                if (Target == null) //This is the case of first iteration
                {
                    GameTimeStamp = targetUpdate.GameTimeStamp - TimeSpan.FromMilliseconds(SettingsSystem.ServerSettings.SecondaryVesselUpdatesMsInterval).TotalSeconds;
                }

                ProcessRestart();
                CurrentFrame = 0;

                if (Target != null)
                {
                    Target.CopyFrom(targetUpdate);
                    VesselPositionSystem.TargetVesselUpdateQueue[VesselId].Recycle(targetUpdate);
                }
                else
                {
                    Target = targetUpdate;
                }

                AdjustExtraInterpolationTimes();

                Vessel?.protoVessel?.UpdatePositionValues(Target);
                VesselsProtoStore.UpdateVesselProtoPosition(this);

                KspOrbit        = new Orbit(Orbit[0], Orbit[1], Orbit[2], Orbit[3], Orbit[4], Orbit[5], Orbit[6], Body);
                Target.KspOrbit = new Orbit(Target.Orbit[0], Target.Orbit[1], Target.Orbit[2], Target.Orbit[3], Target.Orbit[4], Target.Orbit[5], Target.Orbit[6], Target.Body);
            }

            if (Target == null)
            {
                return;
            }
            try
            {
                Vessel.SetVesselPosition(this, Target, LerpPercentage);
            }
            catch (Exception e)
            {
                LunaLog.LogError($"ApplyInterpolations: {e}");
            }
            finally
            {
                CurrentFrame++;
            }
        }
Example #17
0
        public void HandleMessage(IServerMessageBase msg)
        {
            if (!(msg.Data is VesselPositionMsgData msgData))
            {
                return;
            }

            var vesselId = msgData.VesselId;

            //Ignore vessel updates for our own controlled vessel
            if (LockSystem.LockQuery.ControlLockBelongsToPlayer(vesselId, SettingsSystem.CurrentSettings.PlayerName))
            {
                return;
            }

            //Ignore updates if vessel is in kill list
            if (SystemsContainer.Get <VesselRemoveSystem>().VesselWillBeKilled(vesselId))
            {
                return;
            }

            //Vessel might exist in the store but not in game (if the vessel is in safety bubble for example)
            VesselsProtoStore.UpdateVesselProtoPosition(msgData);

            if (!VesselPositionSystem.CurrentVesselUpdate.TryGetValue(vesselId, out var existingPositionUpdate))
            {
                VesselPositionSystem.CurrentVesselUpdate.TryAdd(vesselId, MessageToPositionTransfer.CreateFromMessage(msg));
                VesselPositionSystem.TargetVesselUpdate.TryAdd(vesselId, MessageToPositionTransfer.CreateFromMessage(msg));
            }
            else
            {
                //Here we check that the message timestamp is lower than the message we received. UDP is not reliable and can deliver packets not in order!
                //Also we only process messages if the interpolation is finished
                if (existingPositionUpdate.TimeStamp < msgData.TimeStamp &&
                    VesselPositionSystem.TargetVesselUpdate.TryGetValue(vesselId, out var existingTargetPositionUpdate) && existingTargetPositionUpdate.TimeStamp < msgData.TimeStamp)
                {
                    if (SettingsSystem.CurrentSettings.InterpolationEnabled)
                    {
                        //Here we set the start position to the current VESSEL position in order to LERP correctly
                        existingPositionUpdate.Restart();
                    }
                    else
                    {
                        //Here we just set the interpolation as not started
                        existingPositionUpdate.ResetFields();
                    }

                    //Overwrite the TARGET data with the data we've received in the message
                    MessageToPositionTransfer.UpdateFromMessage(msg, existingTargetPositionUpdate);
                }
            }
        }
Example #18
0
        private static void HandleVesselResponse(VesselsReplyMsgData messageData)
        {
            //We read the vessels syncronously so when we start the game we have the dictionary of all the vessels already loaded
            for (var i = 0; i < messageData.VesselsCount; i++)
            {
                if (!SystemsContainer.Get <VesselRemoveSystem>().VesselWillBeKilled(messageData.VesselsData[i].VesselId))
                {
                    VesselsProtoStore.HandleVesselProtoData(messageData.VesselsData[i].Data, messageData.VesselsData[i].NumBytes, messageData.VesselsData[i].VesselId);
                }
            }

            MainSystem.NetworkState = ClientState.VesselsSynced;
        }
Example #19
0
        public void SendVesselResources(Vessel vessel)
        {
            var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselResourceMsgData>();

            msgData.VesselId = vessel.id;

            var resourcesCount = GetResourcesCount(vessel);

            if (resourcesCount == 0)
            {
                return;                      //No need to send msg if there's no resources in the vessel
            }
            msgData.ResourcesCount = resourcesCount;

            if (_resources.Length < resourcesCount)
            {
                _resources = new VesselResourceInfo[resourcesCount];
            }

            var resourceIndex = 0;

            for (var i = 0; i < vessel.Parts.Count; i++)
            {
                for (var j = 0; j < vessel.Parts[i].Resources.Count; j++)
                {
                    if (_resources[resourceIndex] == null)
                    {
                        _resources[resourceIndex] = new VesselResourceInfo();
                    }

                    _resources[resourceIndex].ResourceName = vessel.Parts[i].Resources[j].resourceName;
                    _resources[resourceIndex].PartFlightId = vessel.Parts[i].flightID;
                    _resources[resourceIndex].Amount       = vessel.Parts[i].Resources[j].amount;

                    resourceIndex++;
                }
            }

            if (msgData.Resources.Length < resourcesCount)
            {
                msgData.Resources = new VesselResourceInfo[resourcesCount];
            }

            Array.Copy(_resources, msgData.Resources, resourcesCount);

            //Update our own values in the store aswell as otherwise if we leave the vessel it can still be in the safety bubble
            VesselsProtoStore.UpdateVesselProtoResources(msgData);

            SendMessage(msgData);
        }
Example #20
0
        public void SendVesselPartSyncMsg(Guid vesselId, uint partFlightId, string moduleName, string baseModuleName, string fieldName, string value)
        {
            var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselPartSyncMsgData>();

            msgData.VesselId       = vesselId;
            msgData.PartFlightId   = partFlightId;
            msgData.ModuleName     = moduleName;
            msgData.BaseModuleName = baseModuleName;
            msgData.FieldName      = fieldName;
            msgData.Value          = value;

            VesselsProtoStore.UpdateVesselProtoPartModules(msgData);
            SendMessage(msgData);
        }
Example #21
0
        protected override void OnDisabled()
        {
            base.OnDisabled();
            TimingManager.FixedUpdateRemove(TimingManager.TimingStage.BetterLateThanNever, CheckVesselsToRefresh);

            GameEvents.onVesselCreate.Remove(VesselProtoEvents.VesselCreate);
            GameEvents.onVesselGoOnRails.Remove(VesselProtoEvents.VesselGoOnRails);
            GameEvents.onFlightReady.Remove(VesselProtoEvents.FlightReady);
            GameEvents.onPartDie.Remove(VesselProtoEvents.OnPartDie);

            //This is the main system that handles the vesselstore so if it's disabled clear the store aswell
            VesselsProtoStore.ClearSystem();
            BannedPartsStr = string.Empty;
        }
Example #22
0
        public void HandleMessage(IServerMessageBase msg)
        {
            if (!(msg.Data is VesselPositionMsgData msgData))
            {
                return;
            }

            var vesselId = msgData.VesselId;

            if (!VesselCommon.DoVesselChecks(vesselId))
            {
                return;
            }

            //Vessel might exist in the store but not in game (if the vessel is in safety bubble for example)
            VesselsProtoStore.UpdateVesselProtoPosition(msgData);

            if (!VesselPositionSystem.CurrentVesselUpdate.TryGetValue(vesselId, out var existingPositionUpdate))
            {
                var current = MessageToPositionTransfer.CreateFromMessage(msg);
                var target  = MessageToPositionTransfer.CreateFromMessage(msg);

                VesselPositionSystem.CurrentVesselUpdate.TryAdd(vesselId, current);
                VesselPositionSystem.TargetVesselUpdate.TryAdd(vesselId, target);
                VesselPositionSystem.TargetVesselUpdateQueue.TryAdd(vesselId, new FixedSizedConcurrentQueue <VesselPositionUpdate>(VesselPositionSystem.MaxQueuedUpdates));

                current.SetTarget(target);
            }
            else
            {
                if (SettingsSystem.CurrentSettings.InterpolationEnabled)
                {
                    if (VesselPositionSystem.TargetVesselUpdateQueue.TryGetValue(vesselId, out var queue))
                    {
                        queue.Enqueue(MessageToPositionTransfer.CreateFromMessage(msg));
                    }
                }
                else
                {
                    if (VesselPositionSystem.TargetVesselUpdate.TryGetValue(vesselId, out var existingTargetPositionUpdate))
                    {
                        //Overwrite the TARGET data with the data we've received in the message
                        MessageToPositionTransfer.UpdateFromMessage(msg, existingTargetPositionUpdate);
                        //Here we just set the interpolation as not started
                        existingPositionUpdate.SetTarget(existingTargetPositionUpdate);
                    }
                }
            }
        }
Example #23
0
        protected override void OnDisabled()
        {
            base.OnDisabled();
            TimingManager.FixedUpdateRemove(TimingManager.TimingStage.BetterLateThanNever, CheckVesselsToRefresh);

            GameEvents.onVesselCreate.Remove(VesselProtoEvents.VesselCreate);
            GameEvents.onFlightReady.Remove(VesselProtoEvents.FlightReady);
            GameEvents.onPartDie.Remove(VesselProtoEvents.OnPartDie);
            GameEvents.onGameSceneLoadRequested.Remove(VesselProtoEvents.OnSceneRequested);
            GameEvents.onVesselPartCountChanged.Remove(VesselProtoEvents.VesselPartCountChangedinSpectatingVessel);
            GameEvents.onVesselPartCountChanged.Remove(VesselProtoEvents.VesselPartCountChanged);

            //This is the main system that handles the vesselstore so if it's disabled clear the store aswell
            VesselsProtoStore.ClearSystem();
        }
Example #24
0
        public void SendVesselFairingDeployed(Vessel vessel, uint partFlightId)
        {
            if (vessel == null)
            {
                return;
            }

            var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselFairingMsgData>();

            msgData.VesselId     = vessel.id;
            msgData.PartFlightId = partFlightId;

            VesselsProtoStore.UpdateVesselProtoPartFairing(msgData);
            SendMessage(msgData);
        }
        public void SendVesselPartSyncMsg(Guid vesselId, uint partFlightId, string moduleName, string baseModuleName, string fieldName, string value)
        {
            var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselPartSyncMsgData>();

            msgData.ServerIgnore   = FieldModuleStore.GetCustomFieldDefinition(moduleName, fieldName)?.ServerIgnore ?? false;
            msgData.GameTime       = TimeSyncerSystem.UniversalTime;
            msgData.VesselId       = vesselId;
            msgData.PartFlightId   = partFlightId;
            msgData.ModuleName     = moduleName;
            msgData.BaseModuleName = baseModuleName;
            msgData.FieldName      = fieldName;
            msgData.Value          = value;

            VesselsProtoStore.UpdateVesselProtoPartModules(msgData);
            SendMessage(msgData);
        }
Example #26
0
        public void SendVesselPositionUpdate(Vessel vessel)
        {
            var msg = MessageToPositionTransfer.CreateMessageFromVessel(vessel);

            if (msg == null)
            {
                return;
            }

            msg.GameTime = Planetarium.GetUniversalTime();

            //Update our own values in the store aswell as otherwise if we leave the vessel it can still be in the safety bubble
            VesselsProtoStore.UpdateVesselProtoPosition(msg);

            SendMessage(msg);
        }
        public void HandleMessage(IServerMessageBase msg)
        {
            if (!(msg.Data is VesselPositionMsgData msgData))
            {
                return;
            }

            var vesselId = msgData.VesselId;

            if (!System.DoVesselChecks(vesselId))
            {
                return;
            }

            //Vessel might exist in the store but not in game (if the vessel is in safety bubble for example)
            VesselsProtoStore.UpdateVesselProtoPosition(msgData);

            if (!VesselPositionSystem.CurrentVesselUpdate.TryGetValue(vesselId, out var existingPositionUpdate))
            {
                var current = MessageToPositionTransfer.CreateFromMessage(msg);
                var target  = MessageToPositionTransfer.CreateFromMessage(msg);

                VesselPositionSystem.CurrentVesselUpdate.TryAdd(vesselId, current);
                VesselPositionSystem.TargetVesselUpdate.TryAdd(vesselId, target);

                current.ResetFields(target);
            }
            else
            {
                if (VesselPositionSystem.TargetVesselUpdate.TryGetValue(vesselId, out var existingTargetPositionUpdate))
                {
                    //Overwrite the TARGET data with the data we've received in the message
                    MessageToPositionTransfer.UpdateFromMessage(msg, existingTargetPositionUpdate);

                    if (SettingsSystem.CurrentSettings.InterpolationEnabled)
                    {
                        //Here we set the start position to the current VESSEL position in order to LERP correctly
                        existingPositionUpdate.Restart(existingTargetPositionUpdate);
                    }
                    else
                    {
                        //Here we just set the interpolation as not started
                        existingPositionUpdate.ResetFields(existingTargetPositionUpdate);
                    }
                }
            }
        }
Example #28
0
        public void HandleMessage(IServerMessageBase msg)
        {
            if (!(msg.Data is VesselFlightStateMsgData msgData))
            {
                return;
            }

            var vesselId = msgData.VesselId;

            if (!VesselCommon.DoVesselChecks(vesselId))
            {
                return;
            }

            //Vessel might exist in the store but not in game (while in KSC for example)
            VesselsProtoStore.UpdateVesselProtoFlightState(msgData);

            //System is not ready nor in use so just skip the message
            if (!System.FlightStateSystemReady)
            {
                return;
            }

            //We are not close (unpacked range) to this vessel so ignore the message
            if (!System.FlyByWireDictionary.ContainsKey(vesselId))
            {
                return;
            }

            if (VesselFlightStateSystem.CurrentFlightState.TryGetValue(vesselId, out var currentFlightState) && currentFlightState.GameTimeStamp > msgData.GameTime)
            {
                //A user reverted, so clear his message queue and start from scratch
                System.RemoveVessel(vesselId);
            }

            if (!VesselFlightStateSystem.CurrentFlightState.ContainsKey(vesselId))
            {
                VesselFlightStateSystem.CurrentFlightState.TryAdd(vesselId, new VesselFlightStateUpdate(msgData));
                VesselFlightStateSystem.TargetFlightStateQueue.TryAdd(vesselId, new FlightStateQueue());
            }
            else
            {
                VesselFlightStateSystem.TargetFlightStateQueue.TryGetValue(vesselId, out var queue);
                queue?.Enqueue(msgData);
            }
        }
Example #29
0
        public void SendEvaData(Vessel vessel, string newState, string eventToRun, float lastBoundStep = float.NaN)
        {
            if (vessel == null)
            {
                return;
            }

            var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselEvaMsgData>();

            msgData.VesselId      = vessel.id;
            msgData.NewState      = newState;
            msgData.EventToRun    = eventToRun;
            msgData.LastBoundStep = lastBoundStep;

            SendMessage(msgData);

            VesselsProtoStore.UpdateVesselProtoEvaFsm(msgData);
        }
        public void SendVesselResources(Vessel vessel)
        {
            _resources.Clear();

            var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselResourceMsgData>();

            msgData.GameTime = TimeSyncerSystem.UniversalTime;
            msgData.VesselId = vessel.id;

            for (var i = 0; i < vessel.protoVessel.protoPartSnapshots.Count; i++)
            {
                for (var j = 0; j < vessel.protoVessel.protoPartSnapshots[i].resources.Count; j++)
                {
                    var protoResource = vessel.protoVessel.protoPartSnapshots[i].resources[j];
                    var resource      = vessel.protoVessel.protoPartSnapshots[i].resources[j].resourceRef;

                    if (resource == null)
                    {
                        continue;
                    }

                    var resourceInfo = new VesselResourceInfo
                    {
                        ResourceName = resource.resourceName,
                        PartFlightId = vessel.protoVessel.protoPartSnapshots[i].flightID,
                        Amount       = resource.amount,
                        FlowState    = resource.flowState
                    };

                    //Now update the proto values our vessel...
                    protoResource.amount    = resource.amount;
                    protoResource.flowState = resource.flowState;

                    _resources.Add(resourceInfo);
                }
            }

            msgData.Resources = _resources.ToArray();

            //Update our own values in the store aswell as otherwise if we leave the vessel it can still be in the safety bubble
            VesselsProtoStore.UpdateVesselProtoResources(msgData);

            SendMessage(msgData);
        }