public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselPositionMsgData msgData)) { return; } var vesselId = msgData.VesselId; if (!VesselCommon.DoVesselChecks(vesselId)) { return; } if (VesselPositionSystem.CurrentVesselUpdate.TryGetValue(vesselId, out var currentUpdate) && currentUpdate.GameTimeStamp > msgData.GameTime) { //A user reverted, so clear it and start from scratch System.RemoveVessel(vesselId); } if (!VesselPositionSystem.CurrentVesselUpdate.ContainsKey(vesselId)) { VesselPositionSystem.CurrentVesselUpdate.TryAdd(vesselId, new VesselPositionUpdate(msgData)); VesselPositionSystem.TargetVesselUpdateQueue.TryAdd(vesselId, new PositionUpdateQueue()); } else { VesselPositionSystem.TargetVesselUpdateQueue.TryGetValue(vesselId, out var queue); queue?.Enqueue(msgData); } }
public void ProcessVesselUpdate() { var vessel = FlightGlobals.fetch.LmpFindVessel(VesselId); if (vessel == null) { return; } if (!VesselCommon.DoVesselChecks(vessel.id)) { return; } var previousSituation = vessel.situation; var previousStage = vessel.currentStage; UpdateVesselFields(vessel); UpdateProtoVesselValues(vessel.protoVessel); //Reload the vessel when the situation changes and vessel is unloaded. //This will also fix the Landed and Splashed fields if (!vessel.loaded && previousSituation != (Vessel.Situations)Enum.Parse(typeof(Vessel.Situations), Situation)) { VesselLoader.LoadVessel(vessel.protoVessel); } //Trigger a reload when staging! if (previousStage != Stage) { VesselLoader.LoadVessel(vessel.protoVessel); } }
public void ProcessPartMethodCallSync() { var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null || !vessel.loaded) { return; } if (!VesselCommon.DoVesselChecks(VesselId)) { return; } var part = vessel.protoVessel.GetProtoPart(PartFlightId); if (part != null) { var module = part.FindProtoPartModuleInProtoPart(ModuleName); if (module != null) { if (module.moduleRef != null) { module.moduleRef.GetType().GetMethod(MethodName, AccessTools.all)?.Invoke(module.moduleRef, null); PartModuleEvent.onPartModuleMethodProcessed.Fire(module, MethodName); } } } }
private void HandleVesselUpdates() { if (!PositionUpdateSystemBasicReady) { return; } foreach (var keyVal in CurrentVesselUpdate) { if (!VesselCommon.DoVesselChecks(keyVal.Key)) { RemoveVesselFromSystem(keyVal.Key); } if (SettingsSystem.CurrentSettings.InterpolationEnabled) { keyVal.Value.ApplyInterpolatedVesselUpdate(); } else { keyVal.Value.ApplyVesselUpdate(); } } while (VesselsToRemove.Count > 0) { var vesselToRemove = VesselsToRemove.Dequeue(); TargetVesselUpdate.TryRemove(vesselToRemove, out _); CurrentVesselUpdate.TryRemove(vesselToRemove, out _); TargetVesselUpdateQueue.TryRemove(vesselToRemove, out _); } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselFairingMsgData msgData) || !System.FairingSystemReady) { 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.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(); } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselPositionMsgData msgData)) { return; } var vesselId = msgData.VesselId; if (!VesselCommon.DoVesselChecks(vesselId)) { return; } if (!VesselPositionSystem.CurrentVesselUpdate.ContainsKey(vesselId)) { VesselPositionSystem.CurrentVesselUpdate.TryAdd(vesselId, new VesselPositionUpdate(msgData)); VesselPositionSystem.TargetVesselUpdateQueue.TryAdd(vesselId, new PositionUpdateQueue()); } else { VesselPositionSystem.TargetVesselUpdateQueue.TryGetValue(vesselId, out var queue); queue?.Enqueue(msgData); } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselDecoupleMsgData msgData)) { return; } //We received a msg for our own controlled/updated vessel so ignore it if (!VesselCommon.DoVesselChecks(msgData.VesselId)) { return; } if (!System.VesselDecouples.ContainsKey(msgData.VesselId)) { System.VesselDecouples.TryAdd(msgData.VesselId, new VesselDecoupleQueue()); } if (System.VesselDecouples.TryGetValue(msgData.VesselId, out var queue)) { if (queue.TryPeek(out var value) && value.GameTime > msgData.GameTime) { //A user reverted, so clear his message queue and start from scratch queue.Clear(); } queue.Enqueue(msgData); } }
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); }
public void ProcessActionGroup() { var vessel = FlightGlobals.fetch.LmpFindVessel(VesselId); if (vessel == null) { return; } if (!VesselCommon.DoVesselChecks(VesselId)) { return; } //Ignore SAS if we are spectating as it will fight with the FI if (ActionGroup == KSPActionGroup.SAS && VesselCommon.IsSpectating && FlightGlobals.ActiveVessel && FlightGlobals.ActiveVessel.id == vessel.id) { return; } if (vessel.ActionGroups != null) { var currentValue = vessel.ActionGroups[ActionGroup]; if (currentValue != Value) { vessel.ActionGroups.ToggleGroup(ActionGroup); } } vessel.protoVessel?.actionGroups.SetValue(ActionGroup.ToString(), $"{Value.ToString(CultureInfo.InvariantCulture)}, 0"); }
public void ProcessPartMethodSync() { var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null) { return; } if (!VesselCommon.DoVesselChecks(VesselId)) { return; } var part = vessel.protoVessel.GetProtoPart(PartFlightId); if (part != null) { var module = part.FindProtoPartModuleInProtoPart(ModuleName); if (module != null) { switch (FieldType) { case PartSyncFieldType.Boolean: module.moduleValues.SetValue(FieldName, BoolValue); if (module.moduleRef != null) { module.moduleRef.Fields[FieldName].SetValue(BoolValue, module.moduleRef); } PartModuleEvent.onPartModuleBoolFieldProcessed.Fire(module, FieldName, BoolValue); break; case PartSyncFieldType.Integer: module.moduleValues.SetValue(FieldName, IntValue); if (module.moduleRef != null) { module.moduleRef.Fields[FieldName].SetValue(IntValue, module.moduleRef); } PartModuleEvent.onPartModuleIntFieldProcessed.Fire(module, FieldName, IntValue); break; case PartSyncFieldType.Float: module.moduleValues.SetValue(FieldName, FloatValue); if (module.moduleRef != null) { module.moduleRef.Fields[FieldName].SetValue(FloatValue, module.moduleRef); } PartModuleEvent.onPartModuleFloatFieldProcessed.Fire(module, FieldName, FloatValue); break; default: throw new ArgumentOutOfRangeException(); } } } }
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); } } } }
public void ProcessVesselResource() { var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null) { return; } if (!VesselCommon.DoVesselChecks(vessel.id)) { return; } UpdateVesselFields(vessel); }
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 ProcessFairing() { if (!VesselCommon.DoVesselChecks(VesselId)) { return; } var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null) { return; } var protoPart = vessel.protoVessel.GetProtoPart(PartFlightId); if (protoPart != null) { ProcessFairingChange(protoPart); } }
public void ProcessVesselUpdate() { var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null) { return; } if (!VesselCommon.DoVesselChecks(vessel.id)) { return; } var previousStage = vessel.currentStage; UpdateVesselFields(vessel); UpdateProtoVesselValues(vessel.protoVessel); if (vessel.orbitDriver && !vessel.loaded) { if (vessel.situation < Vessel.Situations.FLYING && vessel.orbitDriver.updateMode != OrbitDriver.UpdateMode.IDLE) { vessel.orbitDriver.SetOrbitMode(OrbitDriver.UpdateMode.IDLE); } else if (vessel.situation >= Vessel.Situations.FLYING && vessel.orbitDriver.updateMode != OrbitDriver.UpdateMode.UPDATE) { vessel.orbitDriver.SetOrbitMode(OrbitDriver.UpdateMode.UPDATE); } } if (previousStage != Stage) { vessel.currentStage = Stage; if (FlightGlobals.ActiveVessel == vessel) { StageManager.RecalculateVesselStaging(vessel); } } }
public void ProcessFairing() { if (!VesselCommon.DoVesselChecks(VesselId)) { return; } //Finding using persistentId failed, try searching it with the flightId... var vessel = FlightGlobals.fetch.LmpFindVessel(VesselId); if (vessel == null) { return; } var protoPart = VesselCommon.FindProtoPartInProtovessel(vessel.protoVessel, PartFlightId); if (protoPart != null) { ProcessFairingChange(protoPart); } }
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); //System is not ready nor in use so just skip the position message if (!System.PositionUpdateSystemBasicReady) { return; } var update = CreatePosUpdateFromMessage(msgData); if (!VesselPositionSystem.CurrentVesselUpdate.ContainsKey(vesselId)) { VesselPositionSystem.CurrentVesselUpdate.TryAdd(vesselId, update); VesselPositionSystem.TargetVesselUpdateQueue.TryAdd(vesselId, new FixedSizedConcurrentQueue <VesselPositionUpdate>(VesselPositionSystem.MaxQueuedUpdates)); } else { if (VesselPositionSystem.TargetVesselUpdateQueue.TryGetValue(vesselId, out var queue)) { queue.Enqueue(update); } } }
public void ProcessUndock() { if (!VesselCommon.DoVesselChecks(VesselId)) { return; } var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null) { return; } var protoPart = vessel.protoVessel.GetProtoPart(PartFlightId); if (protoPart != null) { if (protoPart.partRef) { VesselUndockSystem.Singleton.ManuallyUndockingVesselId = protoPart.partRef.vessel.id; VesselUndockSystem.Singleton.IgnoreEvents = true; protoPart.partRef.Undock(DockedInfo); protoPart.partRef.vessel.id = NewVesselId; LockSystem.Singleton.FireVesselLocksEvents(NewVesselId); //Forcefully set the vessel as immortal protoPart.partRef.vessel.SetImmortal(true); VesselPositionSystem.Singleton.ForceUpdateVesselPosition(NewVesselId); VesselUndockSystem.Singleton.IgnoreEvents = false; VesselUndockSystem.Singleton.ManuallyUndockingVesselId = Guid.Empty; } } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselPartSyncCallMsgData msgData)) { return; } //We received a msg for our own controlled/updated vessel so ignore it if (!VesselCommon.DoVesselChecks(msgData.VesselId)) { return; } if (!System.VesselPartsSyncs.ContainsKey(msgData.VesselId)) { System.VesselPartsSyncs.TryAdd(msgData.VesselId, new VesselPartSyncCallQueue()); } if (System.VesselPartsSyncs.TryGetValue(msgData.VesselId, out var queue)) { queue.Enqueue(msgData); } }
public void ProcessVesselUpdate() { var vessel = FlightGlobals.fetch.LmpFindVessel(VesselId); if (vessel == null) { return; } if (!VesselCommon.DoVesselChecks(vessel.id)) { return; } var previousStage = vessel.currentStage; UpdateVesselFields(vessel); UpdateProtoVesselValues(vessel.protoVessel); if (vessel.orbitDriver && !vessel.loaded) { if (vessel.situation < Vessel.Situations.FLYING && vessel.orbitDriver.updateMode != OrbitDriver.UpdateMode.IDLE) { vessel.orbitDriver.SetOrbitMode(OrbitDriver.UpdateMode.IDLE); } else if (vessel.situation >= Vessel.Situations.FLYING && vessel.orbitDriver.updateMode != OrbitDriver.UpdateMode.UPDATE) { vessel.orbitDriver.SetOrbitMode(OrbitDriver.UpdateMode.UPDATE); } } //Trigger a reload when staging! if (previousStage != Stage) { VesselLoader.LoadVessel(vessel.protoVessel); } }
public void HandleMessage(IServerMessageBase msg) { if (!(msg.Data is VesselFlightStateMsgData msgData)) { return; } var vesselId = msgData.VesselId; if (!VesselCommon.DoVesselChecks(vesselId)) { return; } //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.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); } }
private static bool ProcessCoupleInternal(Guid vesselId, Guid coupledVesselId, uint partFlightId, uint coupledPartFlightId, CoupleTrigger trigger) { if (!VesselCommon.DoVesselChecks(vesselId)) { return(false); } //If the coupling is against our OWN vessel we must FORCE the loading var forceLoad = FlightGlobals.ActiveVessel && (FlightGlobals.ActiveVessel.id == vesselId || FlightGlobals.ActiveVessel.id == coupledVesselId); _dominantVessel = FlightGlobals.FindVessel(vesselId); if (_dominantVessel == null) { return(false); } if (!_dominantVessel.loaded && forceLoad) { _dominantVessel.Load(); } _weakVessel = FlightGlobals.FindVessel(coupledVesselId); if (_weakVessel == null) { return(false); } if (!_weakVessel.loaded && forceLoad) { _weakVessel.Load(); } var protoPart = _dominantVessel.protoVessel.GetProtoPart(partFlightId); var coupledProtoPart = _weakVessel.protoVessel.GetProtoPart(coupledPartFlightId); if (protoPart != null && coupledProtoPart != null) { if (protoPart.partRef && coupledProtoPart.partRef) { VesselCoupleSystem.Singleton.IgnoreEvents = true; //Remember! The weak vessel must couple with the DOMINANT vessel and not the other way around! switch (trigger) { case CoupleTrigger.DockingNode: var weakDockingNode = coupledProtoPart.partRef.FindModuleImplementing <ModuleDockingNode>(); if (weakDockingNode) { var dominantDockingNode = protoPart.partRef.FindModuleImplementing <ModuleDockingNode>(); if (dominantDockingNode) { weakDockingNode.DockToVessel(dominantDockingNode); } } break; case CoupleTrigger.GrappleNode: var grappleModule = coupledProtoPart.partRef.FindModuleImplementing <ModuleGrappleNode>(); if (grappleModule) { GrappleMethod.Invoke(grappleModule, new object[] { coupledProtoPart, protoPart }); } break; case CoupleTrigger.Kerbal: var kerbalEva = coupledProtoPart.partRef.FindModuleImplementing <KerbalEVA>(); if (kerbalEva) { var seat = KerbalSeatField.GetValue(kerbalEva) as KerbalSeat; if (seat) { kerbalEva.fsm.RunEvent(kerbalEva.On_seatBoard); } } break; case CoupleTrigger.Other: coupledProtoPart.partRef.Couple(protoPart.partRef); break; } VesselCoupleSystem.Singleton.IgnoreEvents = false; return(true); } } return(false); }
public void ProcessPartFieldSync() { var vessel = FlightGlobals.FindVessel(VesselId); if (vessel == null) { return; } if (!VesselCommon.DoVesselChecks(VesselId)) { return; } var part = vessel.protoVessel.GetProtoPart(PartFlightId); var module = part?.FindProtoPartModuleInProtoPart(ModuleName); if (module != null) { switch (FieldType) { case PartSyncFieldType.Boolean: module.moduleValues.SetValue(FieldName, BoolValue); PartModuleEvent.onPartModuleBoolFieldProcessed.Fire(module, FieldName, BoolValue); break; case PartSyncFieldType.Short: module.moduleValues.SetValue(FieldName, ShortValue); PartModuleEvent.onPartModuleShortFieldProcessed.Fire(module, FieldName, ShortValue); break; case PartSyncFieldType.UShort: module.moduleValues.SetValue(FieldName, UShortValue); PartModuleEvent.onPartModuleUShortFieldProcessed.Fire(module, FieldName, UShortValue); break; case PartSyncFieldType.Integer: module.moduleValues.SetValue(FieldName, IntValue); PartModuleEvent.onPartModuleIntFieldProcessed.Fire(module, FieldName, IntValue); break; case PartSyncFieldType.UInteger: module.moduleValues.SetValue(FieldName, UIntValue); PartModuleEvent.onPartModuleUIntFieldProcessed.Fire(module, FieldName, UIntValue); break; case PartSyncFieldType.Float: module.moduleValues.SetValue(FieldName, FloatValue); PartModuleEvent.onPartModuleFloatFieldProcessed.Fire(module, FieldName, FloatValue); break; case PartSyncFieldType.Long: module.moduleValues.SetValue(FieldName, LongValue); PartModuleEvent.onPartModuleLongFieldProcessed.Fire(module, FieldName, LongValue); break; case PartSyncFieldType.ULong: module.moduleValues.SetValue(FieldName, ULongValue); PartModuleEvent.onPartModuleULongFieldProcessed.Fire(module, FieldName, ULongValue); break; case PartSyncFieldType.Double: module.moduleValues.SetValue(FieldName, DoubleValue); PartModuleEvent.onPartModuleDoubleFieldProcessed.Fire(module, FieldName, DoubleValue); break; case PartSyncFieldType.Vector2: module.moduleValues.SetValue(FieldName, Vector2Value); PartModuleEvent.onPartModuleVector2FieldProcessed.Fire(module, FieldName, Vector2Value); break; case PartSyncFieldType.Vector3: module.moduleValues.SetValue(FieldName, Vector3Value); PartModuleEvent.onPartModuleVector3FieldProcessed.Fire(module, FieldName, Vector3Value); break; case PartSyncFieldType.Quaternion: module.moduleValues.SetValue(FieldName, QuaternionValue); PartModuleEvent.onPartModuleQuaternionFieldProcessed.Fire(module, FieldName, QuaternionValue); break; case PartSyncFieldType.String: module.moduleValues.SetValue(FieldName, StrValue); PartModuleEvent.onPartModuleStringFieldProcessed.Fire(module, FieldName, StrValue); break; case PartSyncFieldType.Enum: module.moduleValues.SetValue(FieldName, StrValue); PartModuleEvent.onPartModuleEnumFieldProcessed.Fire(module, FieldName, IntValue, StrValue); break; case PartSyncFieldType.Object: module.moduleValues.SetValue(FieldName, StrValue); PartModuleEvent.onPartModuleObjectFieldProcessed.Fire(module, FieldName, StrValue); //We do not set the value of objects in the module as we cannot be sure if they can be transformed from a string back to the object break; default: throw new ArgumentOutOfRangeException(); } } }