public void Update() { foreach (Guid vesselID in currentVesselUpdates.Keys) { //Not sure if this can happen, but we don't want to apply updates to vessels we are supposed to be updating. if (lockSystem.LockIsOurs("update-" + vesselID)) { continue; } Vessel updateVessel = FlightGlobals.fetch.vessels.Find(v => v.id == vesselID); if (updateVessel == null) { continue; } if (!updateVessel.packed) { continue; } VesselUpdate vu = currentVesselUpdates[vesselID]; //Apply updates for up to 5 seconds double timeDiff = Planetarium.GetUniversalTime() - vu.planetTime; if (timeDiff < 5f && timeDiff > -5f) { vu.Apply(posistionStatistics, null); } } }
private void StepExtrapolateWithRotation(VesselUpdate previous, Vector3d pos, Vector3d vel, Vector3d acc, double timeDiff, out Vector3d newPostion, out Vector3d newVelocity) { Vector3d stepPos = pos; Vector3d stepVel = vel; //Option for adding rotation, this seems to make things worse Quaternion previousRot = new Quaternion(previous.rotation[0], previous.rotation[1], previous.rotation[2], previous.rotation[3]); Quaternion thisRot = new Quaternion(rotation[0], rotation[1], rotation[2], rotation[3]); Quaternion rotDelta = thisRot * Quaternion.Inverse(previousRot); int steps = (int)(Math.Abs(timeDiff) / STEP_DISTANCE); if (steps == 0) { steps = 1; } double actualStepDiff = timeDiff / steps; double rotDiff = planetTime - previous.planetTime; for (int i = 0; i < steps; i++) { double scaling = (i * actualStepDiff) / rotDiff; Quaternion rotAcc = RotationLerp(Quaternion.identity, rotDelta, (float)scaling); Vector3d stepAcc = rotAcc * acc; stepVel = stepVel + stepAcc * actualStepDiff; stepPos = stepPos + stepVel * actualStepDiff; } newPostion = stepPos; newVelocity = stepVel; }
public void SetVesselUpdate(Guid guid, VesselUpdate vesselUpdate) { if (loadingFlyingVessels.ContainsKey(guid)) { loadingFlyingVessels[guid].lastVesselUpdate = vesselUpdate; } }
public void Update() { if (playback) { if (Planetarium.GetUniversalTime() > (lastTime)) { playback = false; ScreenMessages.RemoveMessage(screenMessage); screenMessage = null; } else { int timeLeft = (int)(lastTime - Planetarium.GetUniversalTime()); ScreenMessages.RemoveMessage(screenMessage); screenMessage = ScreenMessages.PostScreenMessage("Playback time left: " + timeLeft + " / " + (int)(lastTime - firstTime) + " seconds", float.MaxValue, ScreenMessageStyle.UPPER_CENTER); } } if (active) { VesselUpdate vu = VesselUpdate.CopyFromVessel(vesselWorker, FlightGlobals.fetch.activeVessel); ClientMessage updateBytes = networkWorker.GetVesselUpdateMessage(vu); byte[] lengthBytes = BitConverter.GetBytes(updateBytes.data.Length); if (BitConverter.IsLittleEndian) { Array.Reverse(lengthBytes); } recordingVector.Write(lengthBytes, 0, lengthBytes.Length); recordingVector.Write(updateBytes.data, 0, updateBytes.data.Length); } }
public void SetNextUpdate(Guid vesselID, VesselUpdate nextUpdate) { if (nextVesselUpdates.ContainsKey(vesselID)) { nextVesselUpdates[vesselID] = nextUpdate; } }
public void StartRecord() { active = true; recording = new MemoryStream(); recordingVector = new MemoryStream(); VesselUpdate update = VesselUpdate.CopyFromVessel(vesselWorker, FlightGlobals.fetch.activeVessel); networkWorker.SendVesselUpdate(update); }
public void StartRecord() { active = true; recording = new MemoryStream(); recordingVector = new MemoryStream(); VesselUpdate update = Recycler <VesselUpdate> .GetObject(); update.SetVesselWorker(vesselWorker); update.CopyFromVessel(FlightGlobals.fetch.activeVessel); networkWorker.SendVesselUpdate(update); Recycler <VesselUpdate> .ReleaseObject(update); }
public void DisplayUpdateVesselOffset() { double interpolatorDelay = 0; if (dmpSettings.interpolatorType == InterpolatorType.INTERPOLATE1S) { interpolatorDelay = 1; } if (dmpSettings.interpolatorType == InterpolatorType.INTERPOLATE3S) { interpolatorDelay = 3; } while (playbackQueue.Count > 0 && Planetarium.GetUniversalTime() > (playbackQueue.Peek().planetTime + interpolatorDelay)) { if (lastUpdate != null) { Recycler <VesselUpdate> .ReleaseObject(lastUpdate); } lastUpdate = playbackQueue.Dequeue(); playbackID = lastUpdate.vesselID; } if (playbackQueue.Count > 0) { VesselUpdate vu = playbackQueue.Peek(); if (lastUpdate != null && vu != null && lastUpdate.isSurfaceUpdate && vu.isSurfaceUpdate) { Vessel av = FlightGlobals.fetch.vessels.Find(v => v.id == vu.vesselID); if (av != null) { double scaling = (Planetarium.GetUniversalTime() - interpolatorDelay - lastUpdate.planetTime) / (vu.planetTime - lastUpdate.planetTime); Vector3d orgPos = new Vector3d(lastUpdate.position[0], lastUpdate.position[1], lastUpdate.position[2]); Vector3d nextPos = new Vector3d(vu.position[0], vu.position[1], vu.position[2]); Vector3d updatePos = Vector3d.Lerp(orgPos, nextPos, scaling); Vector3d distanceInPos = av.mainBody.GetWorldSurfacePosition(av.latitude, av.longitude, av.altitude) - av.mainBody.GetWorldSurfacePosition(updatePos.x, updatePos.y, updatePos.z); double timeDiff = Planetarium.GetUniversalTime() - interpolatorDelay - lastUpdate.planetTime; DarkLog.Debug("Difference in position: " + Math.Round(distanceInPos.magnitude, 3) + ", scaling: " + Math.Round(scaling, 3)); } } } else { //Free the last update too! if (lastUpdate != null) { Recycler <VesselUpdate> .ReleaseObject(lastUpdate); lastUpdate = null; } } }
public void CopyFromUpdate(VesselUpdate source) { updateOK = source.updateOK; SetVesselWorker(source.vesselWorker); vesselID = source.vesselID; planetTime = source.planetTime; bodyName = source.bodyName; rotation[0] = source.rotation[0]; rotation[1] = source.rotation[1]; rotation[2] = source.rotation[2]; rotation[3] = source.rotation[3]; angularVelocity[0] = source.angularVelocity[0]; angularVelocity[1] = source.angularVelocity[1]; angularVelocity[2] = source.angularVelocity[2]; flightState.CopyFrom(source.flightState); actiongroupControls[0] = source.actiongroupControls[0]; actiongroupControls[1] = source.actiongroupControls[1]; actiongroupControls[2] = source.actiongroupControls[2]; actiongroupControls[3] = source.actiongroupControls[3]; actiongroupControls[4] = source.actiongroupControls[4]; isSurfaceUpdate = source.isSurfaceUpdate; terrainNormal[0] = source.terrainNormal[0]; terrainNormal[1] = source.terrainNormal[1]; terrainNormal[2] = source.terrainNormal[2]; velocity[0] = source.velocity[0]; velocity[1] = source.velocity[1]; velocity[2] = source.velocity[2]; acceleration[0] = source.acceleration[0]; acceleration[1] = source.acceleration[1]; acceleration[2] = source.acceleration[2]; orbit[0] = source.orbit[0]; orbit[1] = source.orbit[1]; orbit[2] = source.orbit[2]; orbit[3] = source.orbit[3]; orbit[4] = source.orbit[4]; orbit[5] = source.orbit[5]; orbit[6] = source.orbit[6]; sasEnabled = source.sasEnabled; autopilotMode = source.autopilotMode; lockedRotation[0] = source.lockedRotation[0]; lockedRotation[1] = source.lockedRotation[1]; lockedRotation[2] = source.lockedRotation[2]; lockedRotation[3] = source.lockedRotation[3]; }
public void Update() { foreach (Guid vesselID in currentVesselUpdates.Keys) { //Not sure if this can happen, but we don't want to apply updates to vessels we are supposed to be updating. if (lockSystem.LockIsOurs("update-" + vesselID)) { continue; } Vessel updateVessel = FlightGlobals.fetch.vessels.Find(v => v.id == vesselID); if (updateVessel == null) { continue; } if (!updateVessel.packed && !dmpSettings.interframeEnabled) { return; } if (dmpSettings.interpolatorType == InterpolatorType.DISABLED) { return; } VesselUpdate vu = currentVesselUpdates[vesselID]; VesselUpdate pu = null; if (previousVesselUpdates.ContainsKey(vesselID)) { pu = previousVesselUpdates[vesselID]; } VesselUpdate nu = null; if (nextVesselUpdates.ContainsKey(vesselID)) { nu = nextVesselUpdates[vesselID]; } //Apply updates for up to 5 seconds double timeDiff = Planetarium.GetUniversalTime() - vu.planetTime; if (timeDiff < 5f && timeDiff > -5f) { vu.Apply(posistionStatistics, null, pu, nu, dmpSettings); } } }
private void ApplyVesselUpdate(VesselUpdate update) { if (HighLogic.LoadedScene == GameScenes.LOADING) { return; } //Get updating player string updatePlayer = LockSystem.fetch.LockExists(update.vesselID) ? LockSystem.fetch.LockOwner(update.vesselID) : "Unknown"; //Ignore updates to our own vessel if we are in flight and we aren't spectating if (!isSpectating && (FlightGlobals.fetch.activeVessel != null ? FlightGlobals.fetch.activeVessel.id.ToString() == update.vesselID : false) && HighLogic.LoadedScene == GameScenes.FLIGHT) { DarkLog.Debug("ApplyVesselUpdate - Ignoring update for active vessel from " + updatePlayer); return; } Vessel updateVessel = FlightGlobals.fetch.vessels.FindLast(v => v.id.ToString() == update.vesselID); if (updateVessel == null) { //DarkLog.Debug("ApplyVesselUpdate - Got vessel update for " + update.vesselID + " but vessel does not exist"); return; } CelestialBody updateBody = FlightGlobals.Bodies.Find(b => b.bodyName == update.bodyName); if (updateBody == null) { DarkLog.Debug("ApplyVesselUpdate - updateBody not found"); return; } //Rotation Quaternion updateRotation = new Quaternion(update.rotation[0], update.rotation[1], update.rotation[2], update.rotation[3]); updateVessel.SetRotation(updateVessel.mainBody.bodyTransform.rotation * updateRotation); //Position/Velocity if (update.isSurfaceUpdate) { //Get the new position/velocity Vector3d updatePostion = updateBody.GetWorldSurfacePosition(update.position[0], update.position[1], update.position[2]); Vector3d updateVelocity = updateBody.bodyTransform.rotation * new Vector3d(update.velocity[0], update.velocity[1], update.velocity[2]); //Figure out how far away we are if we can double updateDistance = Double.PositiveInfinity; if ((HighLogic.LoadedScene == GameScenes.FLIGHT) && (FlightGlobals.fetch.activeVessel != null)) { if (FlightGlobals.fetch.activeVessel.mainBody == updateVessel.mainBody) { Vector3d ourPos = FlightGlobals.fetch.activeVessel.mainBody.GetWorldSurfacePosition(FlightGlobals.fetch.activeVessel.latitude, FlightGlobals.fetch.activeVessel.longitude, FlightGlobals.fetch.activeVessel.altitude); Vector3d theirPos = updateVessel.mainBody.GetWorldSurfacePosition(updateVessel.latitude, updateVessel.longitude, updateVessel.altitude); updateDistance = Vector3.Distance(ourPos, theirPos); } } bool isLoading = (updateDistance < Vessel.loadDistance) && !updateVessel.loaded; bool isUnpacking = (updateDistance < updateVessel.distanceUnpackThreshold) && updateVessel.packed && updateVessel.loaded; if (updateVessel.HoldPhysics) { //DarkLog.Debug("Skipping update, physics held"); return; } //Don't set the position while the vessel is unpacking / loading - It doesn't apply properly. if (isUnpacking || isLoading) { //DarkLog.Debug("Skipping update, isUnpacking: " + isUnpacking + " isLoading: " + isLoading); return; } if (updateVessel.packed) { updateVessel.latitude = update.position[0]; updateVessel.longitude = update.position[1]; updateVessel.altitude = update.position[2]; if (!updateVessel.LandedOrSplashed) { //Not landed but under 10km. Vector3d orbitalPos = updatePostion - updateBody.position; Vector3d surfaceOrbitVelDiff = updateBody.getRFrmVel(updatePostion); Vector3d orbitalVel = updateVelocity + surfaceOrbitVelDiff; updateVessel.orbitDriver.orbit.UpdateFromStateVectors(orbitalPos.xzy, orbitalVel.xzy, updateBody, Planetarium.GetUniversalTime()); updateVessel.orbitDriver.pos = updateVessel.orbitDriver.orbit.pos.xzy; updateVessel.orbitDriver.vel = updateVessel.orbitDriver.orbit.vel; /* DarkLog.Debug("updateVelocity: " + (Vector3)updateVelocity + ", |vel| " + updateVelocity.magnitude); DarkLog.Debug("surfaceOrbitVelDiff: " + (Vector3)surfaceOrbitVelDiff + ", |vel| " + surfaceOrbitVelDiff.magnitude); */ /* if (HighLogic.LoadedScene == GameScenes.FLIGHT && FlightGlobals.fetch.activeVessel != null) { DarkLog.Debug("ourVel: " + (Vector3)FlightGlobals.fetch.activeVessel.orbitDriver.vel + ", |vel| " + updateVessel.orbitDriver.vel.magnitude); } DarkLog.Debug("theirVel: " + (Vector3)updateVessel.orbitDriver.vel + ", |vel| " + updateVessel.orbitDriver.vel.magnitude); */ } } else { Vector3d velocityOffset = updateVelocity - updateVessel.srf_velocity; updateVessel.SetPosition(updatePostion, true); updateVessel.ChangeWorldVelocity(velocityOffset); } } else { Orbit updateOrbit = new Orbit(update.orbit[0], update.orbit[1], update.orbit[2], update.orbit[3], update.orbit[4], update.orbit[5], update.orbit[6], updateBody); updateOrbit.Init(); updateOrbit.UpdateFromUT(Planetarium.GetUniversalTime()); if (updateVessel.packed) { //The OrbitDriver update call will set the vessel position on the next fixed update CopyOrbit(updateOrbit, updateVessel.orbitDriver.orbit); updateVessel.orbitDriver.pos = updateVessel.orbitDriver.orbit.pos.xzy; updateVessel.orbitDriver.vel = updateVessel.orbitDriver.orbit.vel; } else { //Vessel.SetPosition is full of fun and games. Avoid at all costs. //Also, It's quite difficult to figure out the world velocity due to Krakensbane, and the reference frame. Vector3d posDelta = updateOrbit.getPositionAtUT(Planetarium.GetUniversalTime()) - updateVessel.orbitDriver.orbit.getPositionAtUT(Planetarium.GetUniversalTime()); Vector3d velDelta = updateOrbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy - updateVessel.orbitDriver.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy; //Vector3d velDelta = updateOrbit.vel.xzy - updateVessel.orbitDriver.orbit.vel.xzy; updateVessel.Translate(posDelta); updateVessel.ChangeWorldVelocity(velDelta); } } //Angular velocity Vector3 angularVelocity = new Vector3(update.angularVelocity[0], update.angularVelocity[1], update.angularVelocity[2]); if (updateVessel.parts != null) { Vector3 newAng = updateVessel.ReferenceTransform.rotation * angularVelocity; foreach (Part vesselPart in updateVessel.parts) { if (vesselPart.rb != null && !vesselPart.rb.isKinematic && vesselPart.State == PartStates.ACTIVE) { //The parts can have different rotations - This transforms them into the root part direction which is where the angular velocity is transferred. vesselPart.rb.angularVelocity = (Quaternion.Inverse(updateVessel.rootPart.rb.rotation) * vesselPart.rb.rotation) * newAng; } } } //Flight state controls (Throttle etc) if (!isSpectating) { updateVessel.ctrlState.CopyFrom(update.flightState); } else { FlightInputHandler.state.CopyFrom(update.flightState); } //Action group controls updateVessel.ActionGroups.SetGroup(KSPActionGroup.Gear, update.actiongroupControls[0]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Light, update.actiongroupControls[1]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, update.actiongroupControls[2]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, update.actiongroupControls[3]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, update.actiongroupControls[4]); }
public void Apply(PosistionStatistics posistionStatistics, Dictionary <Guid, VesselCtrlUpdate> ctrlUpdate, VesselUpdate previousUpdate, VesselUpdate nextUpdate, Settings dmpSettings) { if (HighLogic.LoadedScene == GameScenes.LOADING) { return; } //Ignore updates to our own vessel if we are in flight and we aren't spectating if (!vesselWorker.isSpectating && (FlightGlobals.fetch.activeVessel != null ? FlightGlobals.fetch.activeVessel.id == vesselID : false) && HighLogic.LoadedScene == GameScenes.FLIGHT) { return; } Vessel updateVessel = FlightGlobals.fetch.vessels.FindLast(v => v.id == vesselID); if (updateVessel == null) { //DarkLog.Debug("ApplyVesselUpdate - Got vessel update for " + vesselID + " but vessel does not exist"); return; } CelestialBody updateBody = FlightGlobals.Bodies.Find(b => b.bodyName == bodyName); if (updateBody == null) { //DarkLog.Debug("ApplyVesselUpdate - updateBody not found"); return; } double interpolatorDelay = 0f; if (dmpSettings.interpolatorType == InterpolatorType.INTERPOLATE1S) { interpolatorDelay = 1f; } if (dmpSettings.interpolatorType == InterpolatorType.INTERPOLATE3S) { interpolatorDelay = 3f; } bool interpolatorEnabled = dmpSettings.interpolatorType == InterpolatorType.INTERPOLATE1S || dmpSettings.interpolatorType == InterpolatorType.INTERPOLATE3S; bool extrapolatorEnabled = dmpSettings.interpolatorType == InterpolatorType.EXTRAPOLATE_NO_ROT || dmpSettings.interpolatorType == InterpolatorType.EXTRAPOLATE_FULL; Quaternion normalRotate = Quaternion.identity; Vector3 oldPos = updateVessel.GetWorldPos3D(); Vector3 oldVelocity = updateVessel.orbitDriver.orbit.GetVel(); //Position/Velocity if (isSurfaceUpdate) { //Get the new position/velocity double altitudeFudge = 0; VesselUtil.DMPRaycastPair dmpRaycast = VesselUtil.RaycastGround(position[0], position[1], updateBody); if (dmpRaycast.altitude != -1d && position[3] != -1d) { Vector3 theirNormal = new Vector3(terrainNormal[0], terrainNormal[1], terrainNormal[2]); altitudeFudge = dmpRaycast.altitude - position[3]; if (Math.Abs(position[2] - position[3]) < 50f) { normalRotate = Quaternion.FromToRotation(theirNormal, dmpRaycast.terrainNormal); } } Vector3d updateAcceleration = updateBody.bodyTransform.rotation * new Vector3d(acceleration[0], acceleration[1], acceleration[2]); Vector3d updateVelocity = updateBody.bodyTransform.rotation * new Vector3d(velocity[0], velocity[1], velocity[2]); Vector3d updatePostion = updateBody.GetWorldSurfacePosition(position[0], position[1], position[2] + altitudeFudge); Vector3d newUpdatePostion = updatePostion; Vector3d newUpdateVelocity = updateVelocity; double planetariumDifference = Planetarium.GetUniversalTime() - (planetTime + interpolatorDelay); if (extrapolatorEnabled) { if (Math.Abs(planetariumDifference) < 3f) { if (dmpSettings.interpolatorType == InterpolatorType.EXTRAPOLATE_NO_ROT || previousUpdate == null) { StepExtrapolate(updatePostion, updateVelocity, updateAcceleration, planetariumDifference, out newUpdatePostion, out newUpdateVelocity); } if (dmpSettings.interpolatorType == InterpolatorType.EXTRAPOLATE_FULL && previousUpdate != null) { StepExtrapolateWithRotation(previousUpdate, updatePostion, updateVelocity, updateAcceleration, planetariumDifference, out newUpdatePostion, out newUpdateVelocity); } } } if (interpolatorEnabled && nextUpdate != null && (Math.Abs(nextUpdate.planetTime - Planetarium.GetUniversalTime())) < 5f) { double scaling = (Planetarium.GetUniversalTime() - interpolatorDelay - planetTime) / (nextUpdate.planetTime - planetTime); Vector3d nextPosition = updateBody.GetWorldSurfacePosition(nextUpdate.position[0], nextUpdate.position[1], nextUpdate.position[2] + altitudeFudge); Vector3d nextVelocity = updateBody.bodyTransform.rotation * new Vector3d(nextUpdate.velocity[0], nextUpdate.velocity[1], nextUpdate.velocity[2]); newUpdatePostion = Vector3d.Lerp(updatePostion, nextPosition, scaling); newUpdateVelocity = Vector3d.Lerp(updateVelocity, nextVelocity, scaling); } Vector3d orbitalPos = newUpdatePostion - updateBody.position; Vector3d surfaceOrbitVelDiff = updateBody.getRFrmVel(newUpdatePostion); Vector3d orbitalVel = newUpdateVelocity + surfaceOrbitVelDiff; updateVessel.orbitDriver.orbit.UpdateFromStateVectors(orbitalPos.xzy, orbitalVel.xzy, updateBody, Planetarium.GetUniversalTime()); } else { updateVessel.orbit.SetOrbit(orbit[0], orbit[1], orbit[2], orbit[3], orbit[4], orbit[5], orbit[6], updateBody); } //Updates orbit.pos/vel updateVessel.orbitDriver.orbit.UpdateFromOrbitAtUT(updateVessel.orbitDriver.orbit, Planetarium.GetUniversalTime(), updateBody); //Updates vessel pos from the orbit, as if on rails updateVessel.orbitDriver.updateFromParameters(); //Rotation Quaternion unfudgedRotation = new Quaternion(rotation[0], rotation[1], rotation[2], rotation[3]); //Rotation extrapolation? :O if (previousUpdate != null && (extrapolatorEnabled || (interpolatorEnabled && !isSurfaceUpdate))) { double deltaUpdateT = planetTime - previousUpdate.planetTime; double deltaRealT = Planetarium.GetUniversalTime() - previousUpdate.planetTime; float scaling = (float)(deltaRealT / deltaUpdateT); if (Math.Abs(deltaRealT) < 3f) { Quaternion previousRotation = new Quaternion(previousUpdate.rotation[0], previousUpdate.rotation[1], previousUpdate.rotation[2], previousUpdate.rotation[3]); unfudgedRotation = RotationLerp(previousRotation, unfudgedRotation, scaling); } } if (nextUpdate != null && interpolatorEnabled && isSurfaceUpdate) { double deltaUpdateT = nextUpdate.planetTime - planetTime; double deltaRealT = Planetarium.GetUniversalTime() - interpolatorDelay - planetTime; float scaling = (float)(deltaRealT / deltaUpdateT); if (Math.Abs(deltaRealT) < 3f) { Quaternion nextRotation = new Quaternion(nextUpdate.rotation[0], nextUpdate.rotation[1], nextUpdate.rotation[2], nextUpdate.rotation[3]); unfudgedRotation = RotationLerp(unfudgedRotation, nextRotation, scaling); } } Quaternion updateRotation = normalRotate * unfudgedRotation; //Rotational error tracking double rotationalError = Quaternion.Angle(updateVessel.srfRelRotation, updateRotation); updateVessel.SetRotation(updateVessel.mainBody.bodyTransform.rotation * updateRotation); updateVessel.srfRelRotation = updateRotation; Vector3 angularVel = updateVessel.ReferenceTransform.rotation * new Vector3(angularVelocity[0], angularVelocity[1], angularVelocity[2]); if (updateVessel.parts != null && !updateVessel.packed) { for (int i = 0; i < updateVessel.parts.Count; i++) { Part thisPart = updateVessel.parts[i]; thisPart.vel = updateVessel.orbit.GetVel() - Krakensbane.GetFrameVelocity(); if (thisPart.orbit.referenceBody.inverseRotation) { thisPart.vel -= updateBody.getRFrmVel(thisPart.partTransform.position); } if (thisPart.rb != null && thisPart.State != PartStates.DEAD) { thisPart.rb.velocity = thisPart.vel; //Angular Vel thisPart.rb.angularVelocity = angularVel; if (thisPart != updateVessel.rootPart) { Vector3 diffPos = thisPart.rb.position - updateVessel.CoM; Vector3 partVelDifference = Vector3.Cross(angularVel, diffPos); thisPart.rb.velocity = thisPart.rb.velocity + partVelDifference; } } } } //Updates Vessel.CoMD, which is used for GetWorldPos3D updateVessel.precalc.CalculatePhysicsStats(); updateVessel.latitude = updateBody.GetLatitude(updateVessel.GetWorldPos3D()); updateVessel.longitude = updateBody.GetLongitude(updateVessel.GetWorldPos3D()); updateVessel.altitude = updateBody.GetAltitude(updateVessel.GetWorldPos3D()); double distanceError = Vector3d.Distance(oldPos, updateVessel.GetWorldPos3D()); double velocityError = Vector3d.Distance(oldVelocity, updateVessel.orbitDriver.orbit.GetVel()); if (ctrlUpdate != null) { if (ctrlUpdate.ContainsKey(updateVessel.id)) { updateVessel.OnFlyByWire -= ctrlUpdate[updateVessel.id].UpdateControls; ctrlUpdate.Remove(updateVessel.id); } VesselCtrlUpdate vcu = new VesselCtrlUpdate(updateVessel, ctrlUpdate, planetTime + 5, flightState); ctrlUpdate.Add(updateVessel.id, vcu); updateVessel.OnFlyByWire += vcu.UpdateControls; } //Action group controls updateVessel.ActionGroups.SetGroup(KSPActionGroup.Gear, actiongroupControls[0]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Light, actiongroupControls[1]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, actiongroupControls[2]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, actiongroupControls[3]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, actiongroupControls[4]); if (sasEnabled) { updateVessel.Autopilot.SetMode((VesselAutopilot.AutopilotMode)autopilotMode); updateVessel.Autopilot.SAS.LockRotation(new Quaternion(lockedRotation[0], lockedRotation[1], lockedRotation[2], lockedRotation[3])); } UpdateProtovessel(updateVessel); posistionStatistics.LogError(updateVessel.id, distanceError, velocityError, rotationalError, planetTime); }
public void SetVesselUpdate(Guid vesselID, VesselUpdate vesselUpdate, VesselUpdate previousUpdate, VesselUpdate nextUpdate) { nextVesselUpdates[vesselID] = nextUpdate; currentVesselUpdates[vesselID] = vesselUpdate; previousVesselUpdates[vesselID] = previousUpdate; }
public void QueueVesselUpdate(int subspace, VesselUpdate update) { if (!vesselUpdateQueue.ContainsKey(subspace)) { SetupSubspace(subspace); } vesselUpdateQueue[subspace].Enqueue(update); if (latestVesselUpdate.ContainsKey(update.vesselID) ? latestVesselUpdate[update.vesselID] < update.planetTime : true) { latestVesselUpdate[update.vesselID] = update.planetTime; } }
private void ApplyVesselUpdate(VesselUpdate update) { if (HighLogic.LoadedScene == GameScenes.LOADING) { return; } //Get updating player string updatePlayer = LockSystem.fetch.LockExists(update.vesselID) ? LockSystem.fetch.LockOwner(update.vesselID) : "Unknown"; //Ignore updates to our own vessel if (!isSpectating && (FlightGlobals.ActiveVessel != null ? FlightGlobals.ActiveVessel.id.ToString() == update.vesselID : false)) { DarkLog.Debug("ApplyVesselUpdate - Ignoring update for active vessel from " + updatePlayer); return; } Vessel updateVessel = FlightGlobals.fetch.vessels.FindLast(v => v.id.ToString() == update.vesselID); if (updateVessel == null) { //DarkLog.Debug("ApplyVesselUpdate - Got vessel update for " + update.vesselID + " but vessel does not exist"); return; } CelestialBody updateBody = FlightGlobals.Bodies.Find(b => b.bodyName == update.bodyName); if (updateBody == null) { DarkLog.Debug("ApplyVesselUpdate - updateBody not found"); return; } if (update.isSurfaceUpdate) { double updateDistance = Double.PositiveInfinity; if ((HighLogic.LoadedScene == GameScenes.FLIGHT) && (FlightGlobals.fetch.activeVessel != null)) { updateDistance = Vector3.Distance(FlightGlobals.fetch.activeVessel.GetWorldPos3D(), updateVessel.GetWorldPos3D()); } bool isUnpacking = (updateDistance < updateVessel.distanceUnpackThreshold) && updateVessel.packed; if (!updateVessel.packed && !isUnpacking) { Vector3d updatePostion = updateBody.GetWorldSurfacePosition(update.position[0], update.position[1], update.position[2]); Vector3d updateVelocity = new Vector3d(update.velocity[0], update.velocity[1], update.velocity[2]); Vector3d velocityOffset = updateVelocity - updateVessel.srf_velocity; updateVessel.SetPosition(updatePostion); updateVessel.ChangeWorldVelocity(velocityOffset); } } else { Orbit updateOrbit = new Orbit(update.orbit[0], update.orbit[1], update.orbit[2], update.orbit[3], update.orbit[4], update.orbit[5], update.orbit[6], updateBody); if (updateVessel.packed) { CopyOrbit(updateOrbit, updateVessel.orbitDriver.orbit); } else { updateVessel.SetPosition(updateOrbit.getPositionAtUT(Planetarium.GetUniversalTime())); Vector3d velocityOffset = updateOrbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy - updateVessel.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy; updateVessel.ChangeWorldVelocity(velocityOffset); } } //Quaternion updateRotation = new Quaternion(update.rotation[0], update.rotation[1], update.rotation[2], update.rotation[3]); //updateVessel.SetRotation(updateRotation); Vector3 vesselForward = new Vector3(update.vesselForward[0], update.vesselForward[1], update.vesselForward[2]); Vector3 vesselUp = new Vector3(update.vesselUp[0], update.vesselUp[1], update.vesselUp[2]); updateVessel.transform.LookAt(updateVessel.transform.position + updateVessel.mainBody.transform.TransformDirection(vesselForward).normalized, updateVessel.mainBody.transform.TransformDirection(vesselUp)); updateVessel.SetRotation(updateVessel.transform.rotation); if (!updateVessel.packed) { updateVessel.angularVelocity = new Vector3(update.angularVelocity[0], update.angularVelocity[1], update.angularVelocity[2]); } if (!isSpectating) { updateVessel.ctrlState.CopyFrom(update.flightState); } else { FlightInputHandler.state.CopyFrom(update.flightState); } updateVessel.ActionGroups.SetGroup(KSPActionGroup.Gear, update.actiongroupControls[0]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Light, update.actiongroupControls[1]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, update.actiongroupControls[2]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, update.actiongroupControls[3]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, update.actiongroupControls[4]); }
public void QueueVesselUpdate(VesselUpdate update) { lock (updateQueueLock) { if (!vesselUpdateQueue.ContainsKey(update.vesselID)) { vesselUpdateQueue.Add(update.vesselID, new Queue<VesselUpdate>()); } Queue<VesselUpdate> vuQueue = vesselUpdateQueue[update.vesselID]; if (vesselUpdateHistoryTime.ContainsKey(update.vesselID)) { //If we get an update older than the current queue peek, then someone has gone back in time and the timeline needs to be fixed. if (update.planetTime < vesselUpdateHistoryTime[update.vesselID]) { DarkLog.Debug("Vessel " + update.vesselID + " went back in time - rewriting the update history for it."); Queue<VesselUpdate> newQueue = new Queue<VesselUpdate>(); while (vuQueue.Count > 0) { VesselUpdate oldVu = vuQueue.Dequeue(); //Save the updates from before the revert if (oldVu.planetTime < update.planetTime) { newQueue.Enqueue(oldVu); } } vuQueue = newQueue; vesselUpdateQueue[update.vesselID] = newQueue; //Clean the history too if (Settings.fetch.revertEnabled) { if (vesselUpdateHistory.ContainsKey(update.vesselID)) { List<VesselUpdate> vuh = vesselUpdateHistory[update.vesselID]; foreach (VesselUpdate oldVu in vuh.ToArray()) { if (oldVu.planetTime > update.planetTime) { vuh.Remove(oldVu); } } } } } } vuQueue.Enqueue(update); //Mark the last update time if (latestVesselUpdate.ContainsKey(update.vesselID) ? latestVesselUpdate[update.vesselID] < update.planetTime : true) { latestVesselUpdate[update.vesselID] = update.planetTime; } //Revert support if (Settings.fetch.revertEnabled) { if (!vesselUpdateHistory.ContainsKey(update.vesselID)) { vesselUpdateHistory.Add(update.vesselID, new List<VesselUpdate>()); } vesselUpdateHistory[update.vesselID].Add(update); } vesselUpdateHistoryTime[update.vesselID] = update.planetTime; } }
private void HandleVesselUpdate(byte[] messageData) { VesselUpdate update = new VesselUpdate(); using (MessageReader mr = new MessageReader(messageData, false)) { int subspaceID = mr.Read<int>(); update.planetTime = mr.Read<double>(); update.vesselID = mr.Read<string>(); update.bodyName = mr.Read<string>(); //update.rotation = mr.Read<float[]>(); update.vesselForward = mr.Read<float[]>(); update.vesselUp = mr.Read<float[]>(); update.angularVelocity = mr.Read<float[]>(); update.flightState = new FlightCtrlState(); byte[] flightData = mr.Read<byte[]>(); using (MemoryStream ms = new MemoryStream(flightData)) { ConfigNode flightNode; BinaryFormatter bf = new BinaryFormatter(); flightNode = (ConfigNode)bf.Deserialize(ms); update.flightState.Load(flightNode); } update.actiongroupControls = mr.Read<bool[]>(); update.isSurfaceUpdate = mr.Read<bool>(); if (update.isSurfaceUpdate) { update.position = mr.Read<double[]>(); update.velocity = mr.Read<double[]>(); } else { update.orbit = mr.Read<double[]>(); } VesselWorker.fetch.QueueVesselUpdate(subspaceID, update); } }
//Called from vesselWorker public void SendVesselUpdate(VesselUpdate update) { ClientMessage newMessage = new ClientMessage(); newMessage.type = ClientMessageType.VESSEL_UPDATE; using (MessageWriter mw = new MessageWriter()) { mw.Write<int>(TimeSyncer.fetch.currentSubspace); mw.Write<double>(update.planetTime); mw.Write<string>(update.vesselID); mw.Write<string>(update.bodyName); //mw.Write<float[]>(update.rotation); mw.Write<float[]>(update.vesselForward); mw.Write<float[]>(update.vesselUp); mw.Write<float[]>(update.angularVelocity); using (MemoryStream ms = new MemoryStream()) { ConfigNode flightNode = new ConfigNode(); update.flightState.Save(flightNode); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(ms, flightNode); mw.Write<byte[]>(ms.ToArray()); } mw.Write<bool[]>(update.actiongroupControls); mw.Write<bool>(update.isSurfaceUpdate); if (update.isSurfaceUpdate) { mw.Write<double[]>(update.position); mw.Write<double[]>(update.velocity); } else { mw.Write<double[]>(update.orbit); } newMessage.data = mw.GetMessageBytes(); } sendMessageQueueLow.Enqueue(newMessage); }
private void HandleVesselUpdate(byte[] messageData) { VesselUpdate update = new VesselUpdate(); using (MessageReader mr = new MessageReader(messageData, false)) { update.planetTime = mr.Read<double>(); update.vesselID = mr.Read<string>(); update.bodyName = mr.Read<string>(); update.rotation = mr.Read<float[]>(); update.angularVelocity = mr.Read<float[]>(); //FlightState variables update.flightState = new FlightCtrlState(); update.flightState.mainThrottle = mr.Read<float>(); update.flightState.wheelThrottleTrim = mr.Read<float>(); update.flightState.X = mr.Read<float>(); update.flightState.Y = mr.Read<float>(); update.flightState.Z = mr.Read<float>(); update.flightState.killRot = mr.Read<bool>(); update.flightState.gearUp = mr.Read<bool>(); update.flightState.gearDown = mr.Read<bool>(); update.flightState.headlight = mr.Read<bool>(); update.flightState.wheelThrottle = mr.Read<float>(); update.flightState.fastThrottle = mr.Read<float>(); update.flightState.roll = mr.Read<float>(); update.flightState.yaw = mr.Read<float>(); update.flightState.pitch = mr.Read<float>(); update.flightState.rollTrim = mr.Read<float>(); update.flightState.yawTrim = mr.Read<float>(); update.flightState.pitchTrim = mr.Read<float>(); update.flightState.wheelSteer = mr.Read<float>(); update.flightState.wheelSteerTrim = mr.Read<float>(); //Action group controls update.actiongroupControls = mr.Read<bool[]>(); //Position/velocity update.isSurfaceUpdate = mr.Read<bool>(); if (update.isSurfaceUpdate) { update.position = mr.Read<double[]>(); update.velocity = mr.Read<double[]>(); } else { update.orbit = mr.Read<double[]>(); } VesselWorker.fetch.QueueVesselUpdate(update); } }
public static VesselUpdate CopyFromVessel(VesselWorker vesselWorker, Vessel updateVessel) { VesselUpdate returnUpdate = new VesselUpdate(vesselWorker); try { returnUpdate.vesselID = updateVessel.id; returnUpdate.planetTime = Planetarium.GetUniversalTime(); returnUpdate.bodyName = updateVessel.mainBody.bodyName; returnUpdate.rotation = new float[4]; returnUpdate.rotation[0] = updateVessel.srfRelRotation.x; returnUpdate.rotation[1] = updateVessel.srfRelRotation.y; returnUpdate.rotation[2] = updateVessel.srfRelRotation.z; returnUpdate.rotation[3] = updateVessel.srfRelRotation.w; returnUpdate.angularVelocity = new float[3]; returnUpdate.angularVelocity[0] = updateVessel.angularVelocity.x; returnUpdate.angularVelocity[1] = updateVessel.angularVelocity.y; returnUpdate.angularVelocity[2] = updateVessel.angularVelocity.z; //Flight state returnUpdate.flightState = new FlightCtrlState(); returnUpdate.flightState.CopyFrom(updateVessel.ctrlState); returnUpdate.actiongroupControls = new bool[5]; returnUpdate.actiongroupControls[0] = updateVessel.ActionGroups[KSPActionGroup.Gear]; returnUpdate.actiongroupControls[1] = updateVessel.ActionGroups[KSPActionGroup.Light]; returnUpdate.actiongroupControls[2] = updateVessel.ActionGroups[KSPActionGroup.Brakes]; returnUpdate.actiongroupControls[3] = updateVessel.ActionGroups[KSPActionGroup.SAS]; returnUpdate.actiongroupControls[4] = updateVessel.ActionGroups[KSPActionGroup.RCS]; if (updateVessel.altitude < 10000) { //Use surface position under 10k returnUpdate.isSurfaceUpdate = true; returnUpdate.position = new double[4]; returnUpdate.position[0] = updateVessel.latitude; returnUpdate.position[1] = updateVessel.longitude; returnUpdate.position[2] = updateVessel.altitude; VesselUtil.DMPRaycastPair groundRaycast = VesselUtil.RaycastGround(updateVessel.latitude, updateVessel.longitude, updateVessel.mainBody); returnUpdate.position[3] = groundRaycast.altitude; returnUpdate.terrainNormal = new float[3]; returnUpdate.terrainNormal[0] = groundRaycast.terrainNormal.x; returnUpdate.terrainNormal[1] = groundRaycast.terrainNormal.y; returnUpdate.terrainNormal[2] = groundRaycast.terrainNormal.z; returnUpdate.velocity = new double[3]; Vector3d srfVel = Quaternion.Inverse(updateVessel.mainBody.bodyTransform.rotation) * updateVessel.srf_velocity; returnUpdate.velocity[0] = srfVel.x; returnUpdate.velocity[1] = srfVel.y; returnUpdate.velocity[2] = srfVel.z; returnUpdate.acceleration = new double[3]; Vector3d srfAcceleration = Quaternion.Inverse(updateVessel.mainBody.bodyTransform.rotation) * updateVessel.acceleration; returnUpdate.acceleration[0] = srfAcceleration.x; returnUpdate.acceleration[1] = srfAcceleration.y; returnUpdate.acceleration[2] = srfAcceleration.z; } else { //Use orbital positioning over 10k returnUpdate.isSurfaceUpdate = false; returnUpdate.orbit = new double[7]; returnUpdate.orbit[0] = updateVessel.orbit.inclination; returnUpdate.orbit[1] = updateVessel.orbit.eccentricity; returnUpdate.orbit[2] = updateVessel.orbit.semiMajorAxis; returnUpdate.orbit[3] = updateVessel.orbit.LAN; returnUpdate.orbit[4] = updateVessel.orbit.argumentOfPeriapsis; returnUpdate.orbit[5] = updateVessel.orbit.meanAnomalyAtEpoch; returnUpdate.orbit[6] = updateVessel.orbit.epoch; } returnUpdate.sasEnabled = updateVessel.Autopilot.Enabled; if (returnUpdate.sasEnabled) { returnUpdate.autopilotMode = (int)updateVessel.Autopilot.Mode; returnUpdate.lockedRotation = new float[4]; returnUpdate.lockedRotation[0] = updateVessel.Autopilot.SAS.lockedRotation.x; returnUpdate.lockedRotation[1] = updateVessel.Autopilot.SAS.lockedRotation.y; returnUpdate.lockedRotation[2] = updateVessel.Autopilot.SAS.lockedRotation.z; returnUpdate.lockedRotation[3] = updateVessel.Autopilot.SAS.lockedRotation.w; } } catch (Exception e) { DarkLog.Debug("Failed to get vessel update, exception: " + e); returnUpdate = null; } return(returnUpdate); }
//Called from vesselWorker public void SendVesselUpdate(VesselUpdate update) { ClientMessage newMessage = new ClientMessage(); newMessage.type = ClientMessageType.VESSEL_UPDATE; using (MessageWriter mw = new MessageWriter()) { mw.Write<double>(update.planetTime); mw.Write<string>(update.vesselID); mw.Write<string>(update.bodyName); mw.Write<float[]>(update.rotation); //mw.Write<float[]>(update.vesselForward); //mw.Write<float[]>(update.vesselUp); mw.Write<float[]>(update.angularVelocity); //FlightState variables mw.Write<float>(update.flightState.mainThrottle); mw.Write<float>(update.flightState.wheelThrottleTrim); mw.Write<float>(update.flightState.X); mw.Write<float>(update.flightState.Y); mw.Write<float>(update.flightState.Z); mw.Write<bool>(update.flightState.killRot); mw.Write<bool>(update.flightState.gearUp); mw.Write<bool>(update.flightState.gearDown); mw.Write<bool>(update.flightState.headlight); mw.Write<float>(update.flightState.wheelThrottle); mw.Write<float>(update.flightState.fastThrottle); mw.Write<float>(update.flightState.roll); mw.Write<float>(update.flightState.yaw); mw.Write<float>(update.flightState.pitch); mw.Write<float>(update.flightState.rollTrim); mw.Write<float>(update.flightState.yawTrim); mw.Write<float>(update.flightState.pitchTrim); mw.Write<float>(update.flightState.wheelSteer); mw.Write<float>(update.flightState.wheelSteerTrim); //Action group controls mw.Write<bool[]>(update.actiongroupControls); //Position/velocity mw.Write<bool>(update.isSurfaceUpdate); if (update.isSurfaceUpdate) { mw.Write<double[]>(update.position); mw.Write<double[]>(update.velocity); } else { mw.Write<double[]>(update.orbit); } newMessage.data = mw.GetMessageBytes(); } QueueOutgoingMessage(newMessage, false); }
public void QueueVesselUpdate(VesselUpdate update) { lock (updateQueueLock) { if (!vesselUpdateQueue.ContainsKey(update.vesselID)) { vesselUpdateQueue.Add(update.vesselID, new Queue<VesselUpdate>()); } vesselUpdateQueue[update.vesselID].Enqueue(update); if (latestVesselUpdate.ContainsKey(update.vesselID) ? latestVesselUpdate[update.vesselID] < update.planetTime : true) { latestVesselUpdate[update.vesselID] = update.planetTime; } } }
public void StartPlayback() { int messagesLoaded = 0; bool firstMessage = true; ByteArray headerBytes = ByteRecycler.GetObject(8); using (FileStream fs = new FileStream(recordPath, FileMode.Open)) { while (fs.Position < fs.Length) { messagesLoaded++; fs.Read(headerBytes.data, 0, 8); using (MessageReader mr = new MessageReader(headerBytes.data)) { ClientMessageType messageType = (ClientMessageType)mr.Read <int>(); int length = mr.Read <int>(); ByteArray dataBytes = ByteRecycler.GetObject(length); fs.Read(dataBytes.data, 0, length); using (MessageReader timeReader = new MessageReader(dataBytes.data)) { //Planet time is the first part of the message for the three types we care about here double planetTime = timeReader.Read <double>(); lastTime = planetTime; if (firstMessage) { firstTime = planetTime; firstMessage = false; Planetarium.SetUniversalTime(planetTime - 5d); warpWorker.SendNewSubspace(); } } using (MessageReader mrignore = new MessageReader(dataBytes.data)) { //Planet time, don't care here mrignore.Read <double>(); string vesselID = mrignore.Read <string>(); vesselWorker.IgnoreVessel(new Guid(vesselID)); } switch (messageType) { case ClientMessageType.VESSEL_PROTO: HandleProtoUpdate(dataBytes); break; case ClientMessageType.VESSEL_UPDATE: HandleVesselUpdate(dataBytes, false); break; case ClientMessageType.VESSEL_REMOVE: HandleVesselRemove(dataBytes); break; default: break; } ByteRecycler.ReleaseObject(dataBytes); } } ByteRecycler.ReleaseObject(headerBytes); } playbackQueue = new Queue <VesselUpdate>(); using (FileStream fs = new FileStream(recordVectorPath, FileMode.Open)) { while (fs.Position < fs.Length) { fs.Read(headerBytesInt, 0, 4); if (BitConverter.IsLittleEndian) { Array.Reverse(headerBytesInt); } int updateLength = BitConverter.ToInt32(headerBytesInt, 0); ByteArray updateBytes = ByteRecycler.GetObject(updateLength); fs.Read(updateBytes.data, 0, updateLength); VesselUpdate vu = networkWorker.VeselUpdateFromBytes(updateBytes.data, false); playbackQueue.Enqueue(vu); ByteRecycler.ReleaseObject(updateBytes); } } ScreenMessages.PostScreenMessage("Loaded " + messagesLoaded + " saved updates.", 5f, ScreenMessageStyle.UPPER_CENTER); screenMessage = ScreenMessages.PostScreenMessage("Playback 0 / " + (int)(lastTime - firstTime) + " seconds.", float.MaxValue, ScreenMessageStyle.UPPER_CENTER); playback = true; }
private VesselUpdate GetVesselUpdate(Vessel updateVessel) { VesselUpdate returnUpdate = new VesselUpdate(); try { returnUpdate.vesselID = updateVessel.id.ToString(); returnUpdate.planetTime = Planetarium.GetUniversalTime(); returnUpdate.bodyName = updateVessel.mainBody.bodyName; returnUpdate.rotation = new float[4]; returnUpdate.rotation[0] = updateVessel.srfRelRotation.x; returnUpdate.rotation[1] = updateVessel.srfRelRotation.y; returnUpdate.rotation[2] = updateVessel.srfRelRotation.z; returnUpdate.rotation[3] = updateVessel.srfRelRotation.w; returnUpdate.angularVelocity = new float[3]; returnUpdate.angularVelocity[0] = updateVessel.angularVelocity.x; returnUpdate.angularVelocity[1] = updateVessel.angularVelocity.y; returnUpdate.angularVelocity[2] = updateVessel.angularVelocity.z; //Flight state returnUpdate.flightState = new FlightCtrlState(); returnUpdate.flightState.CopyFrom(updateVessel.ctrlState); returnUpdate.actiongroupControls = new bool[5]; returnUpdate.actiongroupControls[0] = updateVessel.ActionGroups[KSPActionGroup.Gear]; returnUpdate.actiongroupControls[1] = updateVessel.ActionGroups[KSPActionGroup.Light]; returnUpdate.actiongroupControls[2] = updateVessel.ActionGroups[KSPActionGroup.Brakes]; returnUpdate.actiongroupControls[3] = updateVessel.ActionGroups[KSPActionGroup.SAS]; returnUpdate.actiongroupControls[4] = updateVessel.ActionGroups[KSPActionGroup.RCS]; if (updateVessel.altitude < 10000) { //Use surface position under 10k returnUpdate.isSurfaceUpdate = true; returnUpdate.position = new double[3]; returnUpdate.position[0] = updateVessel.latitude; returnUpdate.position[1] = updateVessel.longitude; returnUpdate.position[2] = updateVessel.altitude; returnUpdate.velocity = new double[3]; Vector3d srfVel = Quaternion.Inverse(updateVessel.mainBody.bodyTransform.rotation) * updateVessel.srf_velocity; returnUpdate.velocity[0] = srfVel.x; returnUpdate.velocity[1] = srfVel.y; returnUpdate.velocity[2] = srfVel.z; } else { //Use orbital positioning over 10k returnUpdate.isSurfaceUpdate = false; returnUpdate.orbit = new double[7]; returnUpdate.orbit[0] = updateVessel.orbit.inclination; returnUpdate.orbit[1] = updateVessel.orbit.eccentricity; returnUpdate.orbit[2] = updateVessel.orbit.semiMajorAxis; returnUpdate.orbit[3] = updateVessel.orbit.LAN; returnUpdate.orbit[4] = updateVessel.orbit.argumentOfPeriapsis; returnUpdate.orbit[5] = updateVessel.orbit.meanAnomalyAtEpoch; returnUpdate.orbit[6] = updateVessel.orbit.epoch; } } catch (Exception e) { DarkLog.Debug("Failed to get vessel update, exception: " + e); returnUpdate = null; } return returnUpdate; }
public void SetVesselUpdate(Guid vesselID, VesselUpdate vesselUpdate) { DarkLog.Debug("Vessel update set: " + vesselID); currentVesselUpdates[vesselID] = vesselUpdate; }