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); }
/// <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); } }
/// <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(); } }
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); } }
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); } }
/// <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); } } } }
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); }
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 } }
/// <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); }
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"); } } } }
/// <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++; } }
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); } } }
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; }
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); }
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); }
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; }
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); } } } }
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(); }
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); }
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); } } } }
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); } }
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); }