Example #1
0
        private void writePrimaryUpdate()
        {
            if (!syncing && isInFlight && !warping
                && !isInSafetyBubble(FlightGlobals.ship_position,FlightGlobals.ActiveVessel.mainBody,FlightGlobals.ActiveVessel.altitude))
            {
                lastTick = Planetarium.GetUniversalTime();
                //Write vessel status
                KMPVesselUpdate update = getVesselUpdate(FlightGlobals.ActiveVessel);
                if (FlightGlobals.ActiveVessel.vesselType == VesselType.EVA) lastEVAVessel = FlightGlobals.ActiveVessel;

                //Update the player vessel info
                VesselStatusInfo my_status = new VesselStatusInfo();
                my_status.info = update;
                my_status.orbit = FlightGlobals.ActiveVessel.orbit;
                my_status.color = KMPVessel.generateActiveColor(playerName);
                my_status.ownerName = playerName;
                if (FlightGlobals.ActiveVessel.vesselName.Contains(" <") && FlightGlobals.ActiveVessel.vesselName.Contains(">"))
                    FlightGlobals.ActiveVessel.vesselName = FlightGlobals.ActiveVessel.vesselName.Substring(0,FlightGlobals.ActiveVessel.vesselName.IndexOf(" <"));
                if (String.IsNullOrEmpty(FlightGlobals.ActiveVessel.vesselName.Trim())) FlightGlobals.ActiveVessel.vesselName = "Unknown";
                my_status.vesselName = FlightGlobals.ActiveVessel.vesselName;
                my_status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;

                if (playerStatus.ContainsKey(playerName))
                    playerStatus[playerName] = my_status;
                else
                    playerStatus.Add(playerName, my_status);

                KMPClientMain.DebugLog("sending primary update");
                try{
                    enqueuePluginInteropMessage(KMPCommon.PluginInteropMessageID.PRIMARY_PLUGIN_UPDATE, KSP.IO.IOUtils.SerializeToBinary(update));
                } catch (Exception e) { KMPClientMain.DebugLog("err: " + e.Message); }
            }
            else
            {
                lastTick = 0d;
                //Check if the player is building a ship
                bool building_ship = HighLogic.LoadedSceneIsEditor
                    && EditorLogic.fetch != null
                    && EditorLogic.fetch.ship != null && EditorLogic.fetch.ship.Count > 0
                    && EditorLogic.fetch.shipNameField != null
                    && EditorLogic.fetch.shipNameField.Text != null && EditorLogic.fetch.shipNameField.Text.Length > 0;

                String[] status_array = null;

                if (building_ship)
                {
                    status_array = new String[3];
                    //Vessel name
                    String shipname = EditorLogic.fetch.shipNameField.Text;

                    if (shipname.Length > MAX_VESSEL_NAME_LENGTH)
                        shipname = shipname.Substring(0, MAX_VESSEL_NAME_LENGTH); //Limit vessel name length

                    status_array[1] = "Building " + shipname;

                    //Vessel details
                    status_array[2] = "Parts: " + EditorLogic.fetch.ship.Count;
                }
                else if (warping)
                {
                    status_array = new String[2];
                    status_array[1] = "Warping";
                }
                else if (syncing)
                {
                    status_array = new String[2];
                    status_array[1] = "Synchronizing";
                }
                else
                {
                    status_array = new String[2];

                    switch (HighLogic.LoadedScene)
                    {
                        case GameScenes.FLIGHT:
                            status_array[1] = "Preparing/launching from KSC";
                            break;
                        case GameScenes.SPACECENTER:
                            status_array[1] = "At Space Center";
                            break;
                        case GameScenes.EDITOR:
                            status_array[1] = "In Vehicle Assembly Building";
                            break;
                        case GameScenes.SPH:
                            status_array[1] = "In Space Plane Hangar";
                            break;
                        case GameScenes.TRACKSTATION:
                            status_array[1] = "At Tracking Station";
                            break;
                        default:
                            status_array[1] = String.Empty;
                            break;
                    }
                }

                //Check if player is idle
                if (isIdle)
                    status_array[1] = "(Idle) " + status_array[1];

                status_array[0] = playerName;

                //Serialize the update
                byte[] update_bytes = KSP.IO.IOUtils.SerializeToBinary(status_array);

                enqueuePluginInteropMessage(KMPCommon.PluginInteropMessageID.PRIMARY_PLUGIN_UPDATE, update_bytes);

                VesselStatusInfo my_status = statusArrayToInfo(status_array);
                if (playerStatus.ContainsKey(playerName))
                    playerStatus[playerName] = my_status;
                else
                    playerStatus.Add(playerName, my_status);
            }
        }
Example #2
0
        private VesselStatusInfo statusArrayToInfo(String[] status_array)
        {
            if (status_array != null && status_array.Length >= STATUS_ARRAY_MIN_SIZE)
            {
                //Read status array
                VesselStatusInfo status = new VesselStatusInfo();
                status.info = null;
                status.ownerName = status_array[0];
                status.vesselName = status_array[1];

                if (status_array.Length >= 3)
                    status.detailText = status_array[2];

                if (status_array.Length >= 4 && !String.IsNullOrEmpty(status_array[3]))
                    status.currentSubspaceID = Int32.Parse(status_array[3]);
                else
                    status.currentSubspaceID = -1;

                status.orbit = null;
                status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                status.color = KMPVessel.generateActiveColor(status.ownerName);

                return status;
            }
            else
                return new VesselStatusInfo();
        }
Example #3
0
        private void vesselStatusLabels(VesselStatusInfo status, bool big)
        {
            bool name_pressed = false;
            bool showSync = false;
            playerNameStyle.normal.textColor = status.color * 0.75f + Color.white * 0.25f;

            if (big)
                GUILayout.BeginHorizontal();

            if (status.ownerName != null)
                name_pressed |= GUILayout.Button(status.ownerName, playerNameStyle);

            if (status.vesselName != null && status.vesselName.Length > 0)
            {
                String vessel_name = status.vesselName;

                if (status.currentSubspaceID > 0)
                {
                    showSync = true;
                    showServerSync = true;
                }

                if (status.info != null && status.info.detail != null && status.info.detail.idle)
                    vessel_name = "(Idle) " + vessel_name;

                name_pressed |= GUILayout.Button(vessel_name, vesselNameStyle);
            }

            GUIStyle syncButtonStyle = new GUIStyle(GUI.skin.button);
            syncButtonStyle.normal.textColor = new Color(0.28f, 0.86f, 0.94f);
            syncButtonStyle.hover.textColor = new Color(0.48f, 0.96f, 0.96f);
            syncButtonStyle.margin = new RectOffset(150,10,0,0);
            syncButtonStyle.fixedHeight = 22f;

            if (big)
            {
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
            }
            bool syncRequest = false;
            if (!isInFlight) GUI.enabled = false;
            if (showSync && FlightGlobals.ActiveVessel.ctrlState.mainThrottle == 0f) syncRequest |= GUILayout.Button("Sync",syncButtonStyle);
            GUI.enabled = true;

            if (big)
                GUILayout.EndHorizontal();

            //Build the detail text
            StringBuilder sb = new StringBuilder();

            //Check if the status has specific detail text
            if (status.detailText != null && status.detailText.Length > 0 && KMPInfoDisplay.infoDisplayDetailed)
                sb.Append(status.detailText);
            else if (status.info != null && status.info.detail != null)
            {

                bool exploded = false;
                bool situation_determined = false;

                if (status.info.situation == Situation.DESTROYED || status.info.detail.mass <= 0.0f)
                {
                    sb.Append("Exploded at ");
                    exploded = true;
                    situation_determined = true;
                }
                else
                {

                    //Check if the vessel's activity overrides the situation
                    switch (status.info.detail.activity)
                    {
                        case Activity.AEROBRAKING:
                            sb.Append("Aerobraking at ");
                            situation_determined = true;
                            break;

                        case Activity.DOCKING:
                            if (KMPVessel.situationIsGrounded(status.info.situation))
                                sb.Append("Docking on ");
                            else
                                sb.Append("Docking above ");
                            situation_determined = true;
                            break;

                        case Activity.PARACHUTING:
                            sb.Append("Parachuting to ");
                            situation_determined = true;
                            break;
                    }

                    if (!situation_determined)
                    {
                        switch (status.info.situation)
                        {
                            case Situation.DOCKED:
                                sb.Append("Docked at ");
                                break;

                            case Situation.ENCOUNTERING:
                                sb.Append("Encountering ");
                                break;

                            case Situation.ESCAPING:
                                sb.Append("Escaping ");
                                break;

                            case Situation.FLYING:
                                sb.Append("Flying at ");
                                break;

                            case Situation.LANDED:
                                sb.Append("Landed at ");
                                break;

                            case Situation.ORBITING:
                                sb.Append("Orbiting ");
                                break;

                            case Situation.PRELAUNCH:
                                sb.Append("Prelaunch at ");
                                break;

                            case Situation.SPLASHED:
                                sb.Append("Splashed at ");
                                break;

                            case Situation.ASCENDING:
                                sb.Append("Ascending from ");
                                break;

                            case Situation.DESCENDING:
                                sb.Append("Descending to ");
                                break;
                        }
                    }

                }

                sb.Append(status.info.bodyName);

                if (!exploded && KMPInfoDisplay.infoDisplayDetailed)
                {

                    bool show_mass = status.info.detail.mass >= 0.05f;
                    bool show_fuel = status.info.detail.percentFuel < byte.MaxValue;
                    bool show_rcs = status.info.detail.percentRCS < byte.MaxValue;
                    bool show_crew = status.info.detail.numCrew < byte.MaxValue;

                    if (show_mass || show_fuel || show_rcs || show_crew)
                        sb.Append(" - ");

                    if (show_mass)
                    {
                        sb.Append("Mass: ");
                        sb.Append(status.info.detail.mass.ToString("0.0"));
                        sb.Append(' ');
                    }

                    if (show_fuel)
                    {
                        sb.Append("Fuel: ");
                        sb.Append(status.info.detail.percentFuel);
                        sb.Append("% ");
                    }

                    if (show_rcs)
                    {
                        sb.Append("RCS: ");
                        sb.Append(status.info.detail.percentRCS);
                        sb.Append("% ");
                    }

                    if (show_crew)
                    {
                        sb.Append("Crew: ");
                        sb.Append(status.info.detail.numCrew);
                    }
                }

            }

            if (sb.Length > 0)
                GUILayout.Label(sb.ToString(), stateTextStyle);

            //If the name was pressed, then focus on that players' reference body
            if (name_pressed
                && HighLogic.LoadedSceneHasPlanetarium && planetariumCam != null
                    && status.info != null
                    && status.info.bodyName.Length > 0)
            {
                if (!MapView.MapIsEnabled)
                    MapView.EnterMapView();

                foreach (MapObject target in planetariumCam.targets)
                {
                    if (target.name == status.info.bodyName)
                    {
                        planetariumCam.SetTarget(target);
                        break;
                    }
                }
            }

            if (syncRequest)
                StartCoroutine(sendSubspaceSyncRequest(status.currentSubspaceID));
        }
Example #4
0
        private void applyVesselUpdate(KMPVesselUpdate vessel_update, KMPVessel vessel)
        {
            if (vessel_update.id.ToString() == SYNC_PLATE_ID)
            {
                Log.Debug("Refusing to update sync plate");
                return;
            }

            serverVessels_RemoteID[vessel_update.id] = vessel_update.kmpID;

            //Find the CelestialBody that matches the one in the update
            CelestialBody update_body = null;
            if (vessel.mainBody != null && vessel.mainBody.bodyName == vessel_update.bodyName)
                update_body = vessel.mainBody; //Vessel already has the correct body
            else
            {
                //Find the celestial body in the list of bodies
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    if (body.bodyName == vessel_update.bodyName)
                    {
                        update_body = body;
                        break;
                    }
                }
            }

            if (!vesselUpdatesLoaded.Contains(vessel_update.id)) //This can be moved elsewhere in addRemoteVessel (or applyVesselUpdate) to help track issues with loading a specific vessel
            {
                vesselUpdatesLoaded.Add(vessel_update.id);
            }

            Vector3 oldPosition = vessel.worldPosition;

            if (update_body != null)
            {
                //Convert float arrays to Vector3s
                Vector3 pos = new Vector3(vessel_update.pos[0], vessel_update.pos[1], vessel_update.pos[2]);
                Vector3 dir = new Vector3(vessel_update.dir[0], vessel_update.dir[1], vessel_update.dir[2]);
                Vector3 vel = new Vector3(vessel_update.vel[0], vessel_update.vel[1], vessel_update.vel[2]);
                vessel.info = vessel_update;
                vessel.setOrbitalData(update_body, pos, vel, dir);
            }

            Log.Debug("vessel state: " + vessel_update.state.ToString() + ", tick=" + vessel_update.tick + ", realTick=" + Planetarium.GetUniversalTime());
            if (vessel_update.state == State.ACTIVE && !vessel_update.isSyncOnlyUpdate && vessel_update.relTime != RelativeTime.FUTURE && !vessel_update.isDockUpdate)
            {
                //Update the player status info
                VesselStatusInfo status = new VesselStatusInfo();
                if (vessel_update.relTime == RelativeTime.PRESENT) status.info = vessel_update;
                status.ownerName = vessel_update.player;
                status.vesselName = vessel_update.name;

                if (vessel.orbitValid)
                    status.orbit = vessel.orbitRenderer.driver.orbit;

                status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                status.color = KMPVessel.generateActiveColor(status.ownerName);

                if (playerStatus.ContainsKey(status.ownerName))
                    playerStatus[status.ownerName] = status;
                else
                    playerStatus.Add(status.ownerName, status);
            }

            if (!vessel_update.id.Equals(Guid.Empty) && !docking)
            {
                //Update vessel privacy locks
                serverVessels_InUse[vessel_update.id] = vessel_update.state == State.ACTIVE && !vessel_update.isMine && !vessel_update.isSyncOnlyUpdate;
                serverVessels_IsPrivate[vessel_update.id] = vessel_update.isPrivate;
                serverVessels_IsMine[vessel_update.id] = vessel_update.isMine;
                Log.Debug("status flags updated: " + (vessel_update.state == State.ACTIVE) + " " + vessel_update.isSyncOnlyUpdate + " " + vessel_update.isPrivate + " " + vessel_update.isMine);
                if (vessel_update.situation == Situation.DESTROYED && (isInFlight ? vessel_update.id != FlightGlobals.ActiveVessel.id : true))
                {
                    Log.Debug("Vessel reported destroyed, killing vessel");
                    Vessel extant_vessel = FlightGlobals.Vessels.Find(v => v.id == vessel_update.id);
                    if (extant_vessel != null)
                    {
                        try { killVessel(extant_vessel); } catch (Exception e) { Log.Debug("Exception thrown in applyVesselUpdate(), catch 1, Exception: {0}", e.ToString()); }
                    }
                    return;
                }
            }

            //Store protovessel if included
            if (vessel_update.getProtoVesselNode() != null) serverVessels_ProtoVessels[vessel_update.id] = vessel_update.getProtoVesselNode();

            //Apply update if able
            if (isInFlightOrTracking || syncing)
            {
                if (vessel_update.relativeTo == Guid.Empty && (isInFlight && vessel_update.id != FlightGlobals.ActiveVessel.id || (serverVessels_InUse[vessel_update.id] || (serverVessels_IsPrivate[vessel_update.id] && !serverVessels_IsMine[vessel_update.id]))))
                {
                    if (isInFlight && vessel_update.id == FlightGlobals.ActiveVessel.id && vessel_update.relTime == RelativeTime.PAST) {
                        kickToTrackingStation();
                        return;
                    }
                    Log.Debug("retrieving vessel: " + vessel_update.id.ToString());
                    if (!vessel_update.id.Equals(Guid.Empty))
                    {
                        Vessel extant_vessel = vessel.vesselRef;
                        if (extant_vessel == null) extant_vessel = FlightGlobals.Vessels.Find(v => v.id == vessel_update.id);
                        if (isInFlight)
                        {
                            if (extant_vessel != null && vessel_update.state == State.ACTIVE && !vessel_update.isSyncOnlyUpdate)
                            {
                                 extant_vessel.name = vessel_update.name + " <" + vessel_update.player + ">";
                                 extant_vessel.vesselName = vessel_update.name + " <" + vessel_update.player + ">";
                            }
                            else if (extant_vessel != null)
                            {
                                extant_vessel.name = vessel_update.name;
                                extant_vessel.vesselName = vessel_update.name;
                            }
                        }
            //						if (serverVessels_LoadDelay.ContainsKey(vessel_update.id) ? (serverVessels_LoadDelay[vessel_update.id] < UnityEngine.Time.realtimeSinceStartup) : true)
            //						{
                            float incomingDistance = 2500f;
                            if (!syncing && vessel.worldPosition != Vector3.zero && vessel_update.relTime == RelativeTime.PRESENT)
                                incomingDistance = Vector3.Distance(vessel.worldPosition,FlightGlobals.ship_position);
                            if (vessel_update.relTime != RelativeTime.PRESENT) incomingDistance = 3000f; //Never treat vessels from another time as close by
                         	if (vessel_update.state == State.ACTIVE
                                    || vessel_update.isDockUpdate
                                    || (incomingDistance > vessel_update.distance
                                        && (serverVessels_LastUpdateDistanceTime.ContainsKey(vessel_update.id) ? (serverVessels_LastUpdateDistanceTime[vessel_update.id].Key > vessel_update.distance || serverVessels_LastUpdateDistanceTime[vessel_update.id].Value < Planetarium.GetUniversalTime()): true)))
                            {
                                serverVessels_LastUpdateDistanceTime[vessel_update.id] = new KeyValuePair<double, double>(vessel_update.distance,Planetarium.GetUniversalTime() + 0.75f);
                                if (extant_vessel != null)
                                {
                                    //Log.Debug("vessel found: " + extant_vessel.id);
                                    if (extant_vessel.vesselType != VesselType.Flag) //Special treatment for flags
                                    {
                                        //vessel.vesselRef = extant_vessel;
                                        float ourDistance = 3000f;
                                        if (isInFlight)
                                        {
                                            if (!extant_vessel.loaded)
                                            {
                                                if (KMPVessel.situationIsOrbital(vessel_update.situation))
                                                    ourDistance = Vector3.Distance(extant_vessel.orbit.getPositionAtUT(Planetarium.GetUniversalTime()), FlightGlobals.ship_position);
                                                else ourDistance = Vector3.Distance(oldPosition, FlightGlobals.ship_position);
                                            }
                                        else ourDistance = Vector3.Distance(extant_vessel.GetWorldPos3D(), FlightGlobals.ship_position);
                                        }
                                        bool countMismatch = false;
                                        ProtoVessel protovessel = null;
                                        if (serverVessels_ProtoVessels.ContainsKey(vessel_update.id))
                                        {
                                            ConfigNode protoNode = serverVessels_ProtoVessels[vessel_update.id];
                                            checkProtoNodeCrew(protoNode);
                                            protovessel = new ProtoVessel(protoNode, HighLogic.CurrentGame);
                                        }
                                        if (serverVessels_PartCounts.ContainsKey(vessel_update.id))
                                        {
                                            //countMismatch = serverVessels_PartCounts[vessel_update.id] > 0 && extant_vessel.loaded && !extant_vessel.packed && serverVessels_PartCounts[vessel_update.id] != protovessel.protoPartSnapshots.Count;
                                            countMismatch = serverVessels_PartCounts[vessel_update.id] > 0 && serverVessels_PartCounts[vessel_update.id] != protovessel.protoPartSnapshots.Count;
                                        }
                                        if ((vessel_update.getProtoVesselNode() != null && (!KMPVessel.situationIsOrbital(vessel_update.situation) || ourDistance > 2500f || extant_vessel.altitude < 10000d)) || countMismatch)
                                        {
                                            Log.Debug("updating from protovessel");
                                            serverVessels_PartCounts[vessel_update.id] = 0;
                                            if (protovessel != null)
                                            {
                                                if (vessel.orbitValid && KMPVessel.situationIsOrbital(vessel_update.situation) && protovessel.altitude > 10000f && protovessel.vesselType != VesselType.Flag && protovessel.vesselType != VesselType.EVA && ourDistance > 2500f)
                                                {
                                                    protovessel = syncOrbit(vessel, vessel_update.tick, protovessel, vessel_update.w_pos[0]);
                                                }
                                                if (protovessel == null)
                                                {
                                                    Log.Debug("vessel collided with surface");
                                                    killVessel(extant_vessel);
                                                    return;
                                                }
                                                addRemoteVessel(protovessel, vessel_update.id, vessel, vessel_update, incomingDistance);
                                                if (vessel_update.situation == Situation.FLYING) serverVessels_LoadDelay[vessel.id] = UnityEngine.Time.realtimeSinceStartup + 5f;
                                            } else { Log.Debug("Protovessel missing!"); }
                                        }
                                        else
                                        {
                                            Log.Debug("no protovessel");
                                            if (vessel.orbitValid)
                                            {
                                                Log.Debug("updating from flight data, distance: " + ourDistance);
                                                //Update orbit to our game's time if necessary
                                                //bool throttled = serverVessels_ObtSyncDelay.ContainsKey(vessel_update.id) && serverVessels_ObtSyncDelay[vessel_update.id] > UnityEngine.Time.realtimeSinceStartup;
                                                bool throttled = false;
                                                if (KMPVessel.situationIsOrbital(vessel_update.situation) && extant_vessel.altitude > 10000f)
                                                {
                                                    double tick = Planetarium.GetUniversalTime();
                                                    //Update orbit whenever out of sync or other vessel in past/future, or not in docking range
                          							if (!throttled && !extant_vessel.loaded ||
                                                        (vessel_update.relTime == RelativeTime.PRESENT && (ourDistance > (INACTIVE_VESSEL_RANGE+500f))) ||
                          								(vessel_update.relTime != RelativeTime.PRESENT && Math.Abs(tick-vessel_update.tick) > 1.5d && isInFlight && vessel_update.id != FlightGlobals.ActiveVessel.id))
                                                    {
                                                        if (!syncExtantVesselOrbit(vessel,vessel_update.tick,extant_vessel,vessel_update.w_pos[0]))
                                                        {
                                                            //Collision!
                                                            Log.Debug("vessel collided with surface");
                                                            killVessel(extant_vessel);
                                                            return;
                                                        }
                                                        serverVessels_ObtSyncDelay[vessel_update.id] = UnityEngine.Time.realtimeSinceStartup + 1f;
                                                    }
                                                }

                                                if (isInFlight && FlightGlobals.ActiveVessel.mainBody == update_body && vessel_update.relTime == RelativeTime.PRESENT)
                                                {
                                                    if (!extant_vessel.loaded)
                                                    {
                                                        Log.Debug("Skipped full update, vessel not loaded");
                                                        return;
                                                    }
                                                    Log.Debug("full update");
                                                    if (serverVessels_InPresent.ContainsKey(vessel_update.id) ? !serverVessels_InPresent[vessel_update.id] : true)
                                                    {
                                                        serverVessels_InPresent[vessel_update.id] = true;
                                                        foreach (Part part in extant_vessel.Parts)
                                                        {
                                                            setPartOpacity(part,1f);
                                                        }
                                                    }

                                                    //Update rotation
                                                    if (extant_vessel.loaded)
                                                    {
                                                        Log.Debug("rotation set");

                                                        extant_vessel.transform.LookAt(extant_vessel.transform.position + extant_vessel.mainBody.transform.TransformDirection(new Vector3(vessel_update.rot[0],vessel_update.rot[1],vessel_update.rot[2])).normalized,vessel.worldDirection);
                                                        //Quaternion rot = extant_vessel.transform.rotation;
            //														if (extant_vessel.altitude > 10000f)
            //														{
            //															extant_vessel.transform.up = vessel.worldDirection;
            //															extant_vessel.transform.Rotate(rot.eulerAngles);
                                                            extant_vessel.SetRotation(extant_vessel.transform.rotation);
            //														}
                                                        extant_vessel.angularMomentum = Vector3.zero;
            //														extant_vessel.VesselSAS.LockHeading(extant_vessel.transform.rotation);
            //														extant_vessel.VesselSAS.currentRotation = rot;
                                                        extant_vessel.VesselSAS.SetDampingMode(false);
                                                    }

                                                    if (!KMPVessel.situationIsOrbital(vessel_update.situation) || extant_vessel.altitude < 10000f || vessel_update.id == FlightGlobals.ActiveVessel.id || ourDistance > 2500f)
                                                    {
                                                        Log.Debug ("velocity update");
                                                        //Update velocity
                                                        if (extant_vessel.loaded)
                                                        {
                                                            if (update_body.GetAltitude(vessel.worldPosition)<10000d)
                                                            {
                                                                //Set velocity by surface velocity
                                                                Vector3d new_srf_vel = new Vector3d(vessel_update.s_vel[0],vessel_update.s_vel[1],vessel_update.s_vel[2]);
                                                                if (new_srf_vel.sqrMagnitude>1d) extant_vessel.ChangeWorldVelocity((-1 * extant_vessel.srf_velocity) + new_srf_vel);
                                                                else extant_vessel.ChangeWorldVelocity(-0.99f * extant_vessel.srf_velocity);
                                                            }
                                                            else
                                                            {
                                                                //Set velocity by orbit velocity
                                                                Vector3d new_obt_vel = new Vector3d(vessel_update.o_vel[0],vessel_update.o_vel[1],vessel_update.o_vel[2]);
                                                                if (new_obt_vel.sqrMagnitude>1d) extant_vessel.ChangeWorldVelocity((-1 * extant_vessel.obt_velocity) + new_obt_vel);
                                                                else extant_vessel.ChangeWorldVelocity(-0.99f * extant_vessel.obt_velocity);
                                                            }
                                                        }

                                                        //Update position
                                                        if (extant_vessel.altitude < 10000f || !extant_vessel.loaded || vessel_update.id == FlightGlobals.ActiveVessel.id)
                                                        {
                                                            if (extant_vessel.loaded && (vessel_update.situation == Situation.LANDED || vessel_update.situation == Situation.SPLASHED))
                                                            {
                                                                //Update surface position
                                                                Log.Debug("surface position update");
                                                                Vector3d newPos = update_body.GetWorldSurfacePosition(vessel_update.w_pos[1],vessel_update.w_pos[2],extant_vessel.altitude+0.001d);
                                                                if (extant_vessel.packed) extant_vessel.GoOffRails();
                                                                extant_vessel.distancePackThreshold = Math.Max(extant_vessel.distancePackThreshold,Vector3.Distance(vessel.worldPosition, FlightGlobals.ship_position) + 250f);
                                                                if ((newPos - extant_vessel.GetWorldPos3D()).sqrMagnitude > 1d)
                                                                    extant_vessel.SetPosition(newPos);
                                                                else if (Vector3.Distance(vessel.worldPosition, extant_vessel.GetWorldPos3D()) > 25f)
                                                                {
                                                                    serverVessels_PartCounts[vessel_update.id] = 0;
                                                                    addRemoteVessel(protovessel,vessel_update.id,vessel,vessel_update);
                                                                }
                                                            }
                                                            else if (extant_vessel.loaded && ((!throttled && Vector3.Distance(vessel.worldPosition, extant_vessel.GetWorldPos3D()) > 1
                                                                     && (extant_vessel.altitude < 10000f || ourDistance > 2500f)) || vessel_update.id == FlightGlobals.ActiveVessel.id))
                                                            {
                                                                //Update 3D position
                                                                Log.Debug("position update");
                                                                if (extant_vessel.packed) extant_vessel.GoOffRails();
                                                                extant_vessel.distancePackThreshold = Math.Max(extant_vessel.distancePackThreshold,Vector3.Distance(vessel.worldPosition, FlightGlobals.ship_position) + 250f);
                                                                extant_vessel.SetPosition(vessel.worldPosition);
                                                            }
                                                            else if (!extant_vessel.loaded && Vector3.Distance(vessel.worldPosition, FlightGlobals.ship_position) < 2500f)
                                                            {
                                                                //Stretch packing thresholds to prevent excessive load/unloads during rendezvous initiation
                                                                extant_vessel.distancePackThreshold += 250f;
                                                                extant_vessel.distanceUnpackThreshold += 100f;
                                                            }
                                                            else
                                                            {
                                                                //Reset packing thresholds
                                                                extant_vessel.distancePackThreshold = 7500f;
                                                                extant_vessel.distanceUnpackThreshold = 1000f;
                                                            }
                                                        }

                                                        //Update FlightCtrlState

                                                        if (extant_vessel.id == FlightGlobals.ActiveVessel.id) {
                                                            FlightInputHandler.state.CopyFrom(vessel_update.flightCtrlState.getAsFlightCtrlState(0.75f));
                                                        } else {
                                                            extant_vessel.ctrlState.CopyFrom(vessel_update.flightCtrlState.getAsFlightCtrlState(0.75f));
                                                        }
                                                    }
                                                    else
                                                    {
                                                        if (ourDistance <= 2500f)
                                                        {
                                                            //Orbital rendezvous
                                                            Log.Debug("orbital rendezvous");

                                                            //Keep body-relative orbit intact
                                                            if (!extant_vessel.packed && (serverVessels_SkippedRendezvousUpdates.ContainsKey(extant_vessel.id) ? serverVessels_SkippedRendezvousUpdates[extant_vessel.id] > ALLOW_RENDEZ_OBT_UPDATE_LIMIT : false ))
                                                            {
                                                                serverVessels_SkippedRendezvousUpdates[extant_vessel.id] = -1;
                                                                Vector3d relPos = vessel.worldPosition - extant_vessel.GetWorldPos3D();
                                                                Vector3d relObtVel = new Vector3d(vessel_update.o_vel[0],vessel_update.o_vel[1],vessel_update.o_vel[2])-extant_vessel.obt_velocity;
                                                                if (relPos.sqrMagnitude > RENDEZ_OBT_UPDATE_RELPOS_MIN_SQRMAG || relObtVel.sqrMagnitude > RENDEZ_OBT_UPDATE_RELVEL_MIN_SQRMAG)
                                                                {
                                                                    Log.Debug("syncing relative orbit for mismatch");
                                                                    relPos *= RENDEZ_OBT_UPDATE_SCALE_FACTOR;
                                                                    relObtVel *= RENDEZ_OBT_UPDATE_SCALE_FACTOR;

                                                                    extant_vessel.SetPosition(extant_vessel.GetWorldPos3D() + relPos);
                                                                    FlightGlobals.ActiveVessel.SetPosition(FlightGlobals.ship_position + relPos);

                                                                    FlightGlobals.ActiveVessel.ChangeWorldVelocity(relObtVel);
                                                                    extant_vessel.ChangeWorldVelocity(relObtVel);
                                                                }
                                                            }

                                                            //Update FlightCtrlState
                                                            extant_vessel.ctrlState.CopyFrom(vessel_update.flightCtrlState.getAsFlightCtrlState(0.85f));
                                                        }
                                                    }
                                                }
                                                else if (isInFlight && FlightGlobals.ActiveVessel.mainBody == vessel.mainBody)
                                                {
                                                    Log.Debug("update from past/future");

                                                    if (!serverVessels_InPresent.ContainsKey(vessel_update.id) || serverVessels_InPresent.ContainsKey(vessel_update.id) ? serverVessels_InPresent[vessel_update.id]: false)
                                                    {
                                                        serverVessels_InPresent[vessel_update.id] = false;
                                                        foreach (Part part in extant_vessel.Parts)
                                                        {
                                                            setPartOpacity(part,0.3f);
                                                        }
                                                    }

                                                    //Update rotation only
                                                    extant_vessel.transform.LookAt(extant_vessel.transform.position + extant_vessel.mainBody.transform.TransformDirection(new Vector3(vessel_update.rot[0],vessel_update.rot[1],vessel_update.rot[2])).normalized,vessel.worldDirection);
                                                }
                                            }
                                        }
                                        Log.Debug("updated");
                                    }
                                    else
                                    {
                                        //Update flag if needed
                                        if (vessel_update.getProtoVesselNode() != null)
                                        {
                                            ConfigNode protoNode = serverVessels_ProtoVessels[vessel_update.id];
                                            checkProtoNodeCrew(protoNode);
                                            ProtoVessel protovessel = new ProtoVessel(protoNode, HighLogic.CurrentGame);
                                            addRemoteVessel(protovessel,vessel_update.id,vessel,vessel_update);
                                        }
                                    }
                                }
                                else
                                {
                                    try
                                    {
                                        if (serverVessels_ProtoVessels.ContainsKey(vessel_update.id))
                                        {
                                            Log.Debug("Adding new vessel: " + vessel_update.id);
                                            ConfigNode protoNode = serverVessels_ProtoVessels[vessel_update.id];
                                            checkProtoNodeCrew(protoNode);
                                            ProtoVessel protovessel = new ProtoVessel(protoNode, HighLogic.CurrentGame);
                                            if (vessel.orbitValid && KMPVessel.situationIsOrbital(vessel_update.situation) && protovessel.vesselType != VesselType.Flag)
                                            {
                                                protovessel = syncOrbit(vessel, vessel_update.tick, protovessel, vessel_update.w_pos[0]);
                                            }
                                            if (protovessel == null)
                                            {
                                                Log.Debug("Did not load vessel, has collided with surface");
                                                return;
                                            }
                                            serverVessels_PartCounts[vessel_update.id] = 0;
                                            addRemoteVessel(protovessel, vessel_update.id, vessel, vessel_update, incomingDistance);
                                            HighLogic.CurrentGame.CrewRoster.ValidateAssignments(HighLogic.CurrentGame);
                                        }
                                        else
                                        {
                                            Log.Debug("New vessel, but no matching protovessel available");
                                        }
                                    } catch (Exception e) { Log.Debug("Exception thrown in applyVesselUpdate(), catch 2, Exception: {0}", e.ToString()); Log.Debug("Vessel add error: " + e.Message + "\n" + e.StackTrace); }
                                }
                            }
                            else
                            {
                                Log.Debug("Vessel update ignored: we are closer to target vessel or have recently updated from someone who was closer");
                            }
            //						}
            //						else
            //						{
            //							Log.Debug("Vessel update ignored: target vessel on load delay list");
            //						}
                    }
                }
                else
                {
                    if (isInFlight && vessel_update.id == FlightGlobals.ActiveVessel.id)
                    {
                        Log.Debug("Relative update: " + vessel_update.relativeTo);
                        //This is our vessel!
                        if (vessel_update.getProtoVesselNode() != null)
                        {
                            Log.Debug("Received updated protovessel for active vessel");
                            serverVessels_ProtoVessels[vessel_update.id] = vessel_update.getProtoVesselNode();
                            ConfigNode protoNode = serverVessels_ProtoVessels[vessel_update.id];
                            checkProtoNodeCrew(protoNode);
                            ProtoVessel protovessel = new ProtoVessel(protoNode, HighLogic.CurrentGame);
                            addRemoteVessel(protovessel,vessel_update.id,vessel,vessel_update,0);
                        }

                        if (vessel_update.isDockUpdate && vessel_update.relTime == RelativeTime.PRESENT && !vessel_update.isSyncOnlyUpdate)
                        {
                            //Someone docked with us and has control
                            docking = true;
                            syncing = true;
                            ScreenMessages.PostScreenMessage("Other player has control of newly docked vessel",2.5f,ScreenMessageStyle.UPPER_CENTER);
                            Log.Debug("Received docking update");
                            serverVessels_PartCounts[FlightGlobals.ActiveVessel.id] = 0;
                            serverVessels_InUse[vessel_update.id] = true;
                            return;
                        }
                        //Try to negotiate our relative position with whatever sent this update
                        if (FlightGlobals.ActiveVessel.altitude > 10000d
                            && vessel_update.relativeTo != Guid.Empty
                            && Math.Abs(Planetarium.GetUniversalTime() - vessel_update.tick) < 4d
                            //&& (serverVessels_LoadDelay.ContainsKey(vessel_update.id) ? serverVessels_LoadDelay[vessel_update.id] < UnityEngine.Time.realtimeSinceStartup : true)
                            )
                        {
                            Vessel updateFrom = FlightGlobals.Vessels.Find (v => v.id == vessel_update.relativeTo);
                            if (updateFrom != null && !updateFrom.loaded)
                            {
                                Log.Debug("Rendezvous update from unloaded vessel");
                                if (vessel_update.distance < INACTIVE_VESSEL_RANGE)
                                {
                                    //We're not in normal secondary vessel range but other vessel is, send negotiating reply
                                    KMPVesselUpdate update = getVesselUpdate(updateFrom);
                                    update.distance = INACTIVE_VESSEL_RANGE;
                                    update.state = State.INACTIVE;
                                    //Rendezvous relative position data
                                    update.relativeTo = FlightGlobals.ActiveVessel.id;
                                    Vector3d w_pos = FlightGlobals.ActiveVessel.mainBody.transform.InverseTransformDirection(updateFrom.findWorldCenterOfMass() - activeVesselPosition);
                                    Vector3d o_vel = FlightGlobals.ActiveVessel.mainBody.transform.InverseTransformDirection(updateFrom.GetObtVelocity() - FlightGlobals.ActiveVessel.GetObtVelocity());
                                    for (int i = 0; i < 3; i++)
                                    {
                                        update.w_pos[i] = w_pos[i];
                                        update.o_vel[i] = o_vel[i];
                                    }

                                    byte[] update_bytes = KSP.IO.IOUtils.SerializeToBinary(update);
                                    enqueuePluginInteropMessage(KMPCommon.PluginInteropMessageID.SECONDARY_PLUGIN_UPDATE, update_bytes);

                                    //updateFrom.distancePackThreshold += INACTIVE_VESSEL_RANGE/2;
                                }
                            }
                            else if (updateFrom != null && updateFrom.loaded)
                            {
                                Log.Debug("rendezvous positioning: " + updateFrom.id);

                                Vector3d updateFromPos = updateFrom.packed ? updateFrom.GetWorldPos3D() : (Vector3d) updateFrom.findWorldCenterOfMass();
                                Vector3d relPos = activeVesselPosition-updateFromPos;
                                Vector3d updateRelPos = updateFrom.mainBody.transform.TransformDirection(new Vector3d(vessel_update.w_pos[0],vessel_update.w_pos[1],vessel_update.w_pos[2]));

                                if (!dockingRelVel.ContainsKey(updateFrom.id))
                                    dockingRelVel[updateFrom.id] = updateFrom.GetObtVelocity();

                                Vector3d relVel = FlightGlobals.ActiveVessel.GetObtVelocity()-dockingRelVel[updateFrom.id];
                                Vector3d updateRelVel = updateFrom.mainBody.transform.TransformDirection(new Vector3d(vessel_update.o_vel[0],vessel_update.o_vel[1],vessel_update.o_vel[2]));
                                Vector3d diffPos = updateRelPos - relPos;
                                Vector3d diffVel = updateRelVel - relVel;
                                diffPos *= 0.49d;
                                diffVel *= 0.49d;
                                Vector3d newPos = updateFromPos-diffPos;

                                if (!serverVessels_SkippedRendezvousUpdates.ContainsKey(updateFrom.id)) serverVessels_SkippedRendezvousUpdates[updateFrom.id] = 0;

                                bool applyUpdate = true;
                                double curTick = Planetarium.GetUniversalTime();
                                if (vessel_update.distance <= INACTIVE_VESSEL_RANGE && serverVessels_SkippedRendezvousUpdates[updateFrom.id] != -1) //If distance >= INACTIVE_VESSEL_RANGE then the other player didn't have us loaded--don't ignore even a large correction in this case
                                {
                                    bool smoothPosCheck = (serverVessels_RendezvousSmoothPos.ContainsKey(updateFrom.id) ? (diffPos.sqrMagnitude > (serverVessels_RendezvousSmoothPos[updateFrom.id].Key * SMOOTH_RENDEZ_UPDATE_MAX_DIFFPOS_SQRMAG_INCREASE_SCALE) && diffPos.sqrMagnitude > 1d && serverVessels_RendezvousSmoothPos[updateFrom.id].Value > (curTick-SMOOTH_RENDEZ_UPDATE_EXPIRE)): false);
                                    if ((serverVessels_RendezvousSmoothPos.ContainsKey(updateFrom.id) ? serverVessels_RendezvousSmoothPos[updateFrom.id].Value > (curTick-SMOOTH_RENDEZ_UPDATE_MIN_DELAY) : false) || smoothPosCheck)
                                    {
                                        applyUpdate = false;
                                        if (smoothPosCheck)
                                            serverVessels_SkippedRendezvousUpdates[updateFrom.id]++;
                                    }
                                    if (serverVessels_RendezvousSmoothVel.ContainsKey(updateFrom.id) ? (diffVel.sqrMagnitude > (serverVessels_RendezvousSmoothVel[updateFrom.id].Key * SMOOTH_RENDEZ_UPDATE_MAX_DIFFVEL_SQRMAG_INCREASE_SCALE) && diffVel.sqrMagnitude > 1d && serverVessels_RendezvousSmoothVel[updateFrom.id].Value > (curTick-SMOOTH_RENDEZ_UPDATE_EXPIRE)): false)
                                    {
                                        serverVessels_SkippedRendezvousUpdates[updateFrom.id]++;
                                        applyUpdate = false;
                                    }
                                }

                                double expectedDist = Vector3d.Distance(newPos, activeVesselPosition);
                                if (applyUpdate)
                                {
                                    serverVessels_RendezvousSmoothPos[updateFrom.id] = new KeyValuePair<double, double>(diffPos.sqrMagnitude,curTick);
                                    serverVessels_RendezvousSmoothVel[updateFrom.id] = new KeyValuePair<double, double>(diffVel.sqrMagnitude,curTick);
                                    serverVessels_SkippedRendezvousUpdates[updateFrom.id] = 0;
                                    try
                                    {
                                        OrbitPhysicsManager.HoldVesselUnpack(1);
                                    }
                                    catch (NullReferenceException e)
                                    {
                                        Log.Debug("Exception thrown in applyVesselUpdate(), catch 3, Exception: {0}", e.ToString());
                                    }

                                    if (diffPos.sqrMagnitude < 1000000d && diffPos.sqrMagnitude > 0.05d)
                                    {
                                        Log.Debug("Docking Krakensbane shift");
                                        foreach (Vessel otherVessel in FlightGlobals.Vessels.Where(v => v.packed == false && v.id != FlightGlobals.ActiveVessel.id && v.id == updateFrom.id))
                                            otherVessel.GoOnRails();
                                        getKrakensbane().setOffset(diffPos);
                                    }
                                    else if (diffPos.sqrMagnitude >= 1000000d)
                                    {
                                        Log.Debug("Clamped docking Krakensbane shift");
                                        diffPos.Normalize();
                                        diffPos *= 1000d;
                                        foreach (Vessel otherVessel in FlightGlobals.Vessels.Where(v => v.packed == false && v.id != FlightGlobals.ActiveVessel.id))
                                            otherVessel.GoOnRails();
                                        getKrakensbane().setOffset(diffPos);
                                    }

                                    activeVesselPosition += diffPos;

                                    if (diffVel.sqrMagnitude > 0.0025d && diffVel.sqrMagnitude < 2500d)
                                    {
                                        Log.Debug("Docking velocity update");
                                        if (updateFrom.packed) updateFrom.GoOffRails();
                                        updateFrom.ChangeWorldVelocity(-diffVel);
                                    }
                                    else if (diffVel.sqrMagnitude >= 2500d)
                                    {
                                        Log.Debug("Damping large velocity differential");
                                        diffVel = diffVel.normalized;
                                        diffVel *= 50d;
                                        if (updateFrom.packed) updateFrom.GoOffRails();
                                        updateFrom.ChangeWorldVelocity(-diffVel);
                                    }

                                    dockingRelVel[updateFrom.id] -= diffVel;
                                }
                                else Log.Debug("Ignored docking position update: unexpected large pos/vel shift");

                                Log.Debug("had dist:" + relPos.magnitude + " got dist:" + updateRelPos.magnitude);
                                Log.Debug("expected dist:" + expectedDist + " diffPos mag: " + diffPos.sqrMagnitude);
                                Log.Debug("had relVel:" + relVel.magnitude + " got relVel:" + updateRelVel.magnitude + " diffVel mag:" + diffVel.sqrMagnitude);
                            }
                        } else Log.Debug("Ignored docking position update: " + (FlightGlobals.ActiveVessel.altitude > 10000d) + " " + (vessel_update.relativeTo != Guid.Empty) + " " + (Math.Abs(Planetarium.GetUniversalTime() - vessel_update.tick) < 1d));
                    }
                }
            }
        }
Example #5
0
        private void applyVesselUpdate(KMPVesselUpdate vessel_update, KMPVessel vessel)
        {
            serverVessels_RemoteID[vessel_update.id] = vessel_update.kmpID;

            //Find the CelestialBody that matches the one in the update
            CelestialBody update_body = null;
            if (vessel.mainBody != null && vessel.mainBody.bodyName == vessel_update.bodyName)
                update_body = vessel.mainBody; //Vessel already has the correct body
            else
            {
                //Find the celestial body in the list of bodies
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    if (body.bodyName == vessel_update.bodyName)
                    {
                        update_body = body;
                        break;
                    }
                }
            }

            Vector3 oldPosition = vessel.worldPosition;

            if (update_body != null)
            {
                //Convert float arrays to Vector3s
                Vector3 pos = new Vector3(vessel_update.pos[0], vessel_update.pos[1], vessel_update.pos[2]);
                Vector3 dir = new Vector3(vessel_update.dir[0], vessel_update.dir[1], vessel_update.dir[2]);
                Vector3 vel = new Vector3(vessel_update.vel[0], vessel_update.vel[1], vessel_update.vel[2]);
                vessel.info = vessel_update;
                vessel.setOrbitalData(update_body, pos, vel, dir);
            }

            KMPClientMain.DebugLog("vessel state: " + vessel_update.state.ToString() + ", tick=" + vessel_update.tick + ", realTick=" + Planetarium.GetUniversalTime());
            if (vessel_update.state == State.ACTIVE && !vessel_update.isSyncOnlyUpdate && vessel_update.relTime != RelativeTime.FUTURE && !vessel_update.isDockUpdate)
            {
                //Update the player status info
                VesselStatusInfo status = new VesselStatusInfo();
                if (vessel_update.relTime == RelativeTime.PRESENT) status.info = vessel_update;
                status.ownerName = vessel_update.player;
                status.vesselName = vessel_update.name;

                if (vessel.orbitValid)
                    status.orbit = vessel.orbitRenderer.driver.orbit;

                status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                status.color = KMPVessel.generateActiveColor(status.ownerName);

                if (playerStatus.ContainsKey(status.ownerName))
                    playerStatus[status.ownerName] = status;
                else
                    playerStatus.Add(status.ownerName, status);
            }
            if (!vessel_update.id.Equals(Guid.Empty) && !docking)
            {
                //Update vessel privacy locks
                if (!isInFlight || vessel_update.id != FlightGlobals.ActiveVessel.id)
                {
                    serverVessels_InUse[vessel_update.id] = vessel_update.state == State.ACTIVE;
                    serverVessels_IsPrivate[vessel_update.id] = vessel_update.isPrivate;
                    serverVessels_IsMine[vessel_update.id] = vessel_update.isMine;
                    KMPClientMain.DebugLog("status flags updated: " + (vessel_update.state == State.ACTIVE) + " " + vessel_update.isPrivate + " " + vessel_update.isMine);
                    if (vessel_update.situation == Situation.DESTROYED)
                    {
                        KMPClientMain.DebugLog("killing vessel");
                        Vessel extant_vessel = FlightGlobals.Vessels.Find(v => v.id == vessel_update.id);
                        if (extant_vessel != null && !extant_vessel.isEVA) try { extant_vessel.Die(); } catch {}
                        return;
                    }
                }

                //Store protovessel if included
                if (vessel_update.getProtoVesselNode() != null && (!isInFlight || vessel_update.id != FlightGlobals.ActiveVessel.id)) serverVessels_ProtoVessels[vessel_update.id] = vessel_update.getProtoVesselNode();
            }
            if (isInFlightOrTracking)
            {
                if (vessel_update.id != FlightGlobals.ActiveVessel.id)
                {
                    KMPClientMain.DebugLog("retrieving vessel: " + vessel_update.id.ToString());
                    if (!vessel_update.id.Equals(Guid.Empty))
                    {
                        Vessel extant_vessel = vessel.vesselRef;
                        if (extant_vessel == null) extant_vessel = FlightGlobals.Vessels.Find(v => v.id == vessel_update.id);
                        if (isInFlight)
                        {
                            if (extant_vessel != null && vessel_update.state == State.ACTIVE && !vessel_update.isSyncOnlyUpdate)
                            {
                                 extant_vessel.name = vessel_update.name + " <" + vessel_update.player + ">";
                                 extant_vessel.vesselName = vessel_update.name + " <" + vessel_update.player + ">";
                            }
                            else if (extant_vessel != null)
                            {
                                extant_vessel.name = vessel_update.name;
                                extant_vessel.vesselName = vessel_update.name;
                            }
                        }
                        if (!serverVessels_LoadDelay.ContainsKey(vessel_update.id)
                            || (serverVessels_LoadDelay.ContainsKey(vessel_update.id) ? (serverVessels_LoadDelay[vessel_update.id] < UnityEngine.Time.realtimeSinceStartup) : false))
                        {
                            float incomingDistance = 2500f;
                            if (!syncing && vessel.worldPosition != Vector3.zero && vessel_update.relTime == RelativeTime.PRESENT)
                                incomingDistance = Vector3.Distance(vessel.worldPosition,FlightGlobals.ship_position);
                            if (vessel_update.relTime != RelativeTime.PRESENT) incomingDistance = 3000f; //Never treat vessels from another time as close by
                         	if (vessel_update.state == State.ACTIVE
                                    || vessel_update.isDockUpdate
                                    || (incomingDistance > vessel_update.distance
                                        && (serverVessels_LastUpdateDistanceTime.ContainsKey(vessel_update.id) ? (serverVessels_LastUpdateDistanceTime[vessel_update.id].Key > vessel_update.distance || serverVessels_LastUpdateDistanceTime[vessel_update.id].Value < Planetarium.GetUniversalTime()): true)))
                            {
                                serverVessels_LastUpdateDistanceTime[vessel_update.id] = new KeyValuePair<double, double>(vessel_update.distance,Planetarium.GetUniversalTime() + 0.75f);
                                if (extant_vessel != null)
                                {
                                    KMPClientMain.DebugLog("vessel found: " + extant_vessel.id);
                                    if (extant_vessel.vesselType != VesselType.Flag) //Special treatment for flags
                                    {
                                        vessel.vesselRef = extant_vessel;
                                        float ourDistance = 3000f;
                                        if (!extant_vessel.loaded)
                                        {
                                            if (KMPVessel.situationIsOrbital(vessel_update.situation))
                                                ourDistance = Vector3.Distance(extant_vessel.orbit.getPositionAtUT(Planetarium.GetUniversalTime()), FlightGlobals.ship_position);
                                            else ourDistance = Vector3.Distance(oldPosition, FlightGlobals.ship_position);
                                        }
                                        else ourDistance = Vector3.Distance(extant_vessel.GetWorldPos3D(), FlightGlobals.ship_position);
                                        bool countMismatch = false;
                                        ProtoVessel protovessel = null;
                                        if (serverVessels_ProtoVessels.ContainsKey(vessel_update.id))
                                        {
                                            protovessel = new ProtoVessel(serverVessels_ProtoVessels[vessel_update.id], HighLogic.CurrentGame);
                                        }
                                        if (serverVessels_PartCounts.ContainsKey(vessel_update.id))
                                        {
                                            //countMismatch = serverVessels_PartCounts[vessel_update.id] > 0 && extant_vessel.loaded && !extant_vessel.packed && serverVessels_PartCounts[vessel_update.id] != protovessel.protoPartSnapshots.Count;
                                            countMismatch = serverVessels_PartCounts[vessel_update.id] > 0 && serverVessels_PartCounts[vessel_update.id] != protovessel.protoPartSnapshots.Count;
                                        }
                                        if ((vessel_update.getProtoVesselNode() != null && (!KMPVessel.situationIsOrbital(vessel_update.situation) || ourDistance > 2500f || extant_vessel.altitude < 10000d)) || countMismatch)
                                        {
                                            KMPClientMain.DebugLog("updating from protovessel");
                                            serverVessels_PartCounts[vessel_update.id] = 0;
                                            if (protovessel != null)
                                            {
                                                if (vessel.orbitValid && KMPVessel.situationIsOrbital(vessel_update.situation) && protovessel.altitude > 10000f && protovessel.vesselType != VesselType.Flag && protovessel.vesselType != VesselType.EVA)
                                                {
                                                    protovessel = syncOrbit(vessel, vessel_update.tick, protovessel, vessel_update.w_pos[0]);
                                                }
                                                addRemoteVessel(protovessel, vessel_update.id, vessel_update, incomingDistance);
                                                if (vessel_update.situation == Situation.FLYING) serverVessels_LoadDelay[vessel.id] = UnityEngine.Time.realtimeSinceStartup + 5f;
                                            } else { KMPClientMain.DebugLog("Protovessel missing!"); }
                                        }
                                        else
                                        {
                                            KMPClientMain.DebugLog("no protovessel");
                                            if (vessel.orbitValid && !extant_vessel.isActiveVessel)
                                            {
                                                KMPClientMain.DebugLog("updating from flight data, distance: " + ourDistance);
                                                //Update orbit to our game's time if necessary
                                                //bool throttled = serverVessels_ObtSyncDelay.ContainsKey(vessel_update.id) && serverVessels_ObtSyncDelay[vessel_update.id] > UnityEngine.Time.realtimeSinceStartup;
                                                bool throttled = false;
                                                if (KMPVessel.situationIsOrbital(vessel_update.situation) && extant_vessel.altitude > 10000f)
                                                {
                                                    double tick = Planetarium.GetUniversalTime();
                                                    //Update orbit whenever out of sync or other vessel in past/future, or not in docking range
                                                    if (!throttled && (vessel_update.relTime == RelativeTime.PRESENT && ourDistance > (INACTIVE_VESSEL_RANGE+500f)) || (vessel_update.relTime != RelativeTime.PRESENT && Math.Abs(tick-vessel_update.tick) > 1.5d))
                                                    {
                                                        syncExtantVesselOrbit(vessel,vessel_update.tick,extant_vessel,vessel_update.w_pos[0]);
                                                        serverVessels_ObtSyncDelay[vessel_update.id] = UnityEngine.Time.realtimeSinceStartup + 1f;
                                                    }
                                                }

                                                if (FlightGlobals.ActiveVessel.mainBody == update_body && vessel_update.relTime == RelativeTime.PRESENT)
                                                {
                                                    KMPClientMain.DebugLog("full update");
                                                    if (serverVessels_InPresent.ContainsKey(vessel_update.id) ? !serverVessels_InPresent[vessel_update.id] : true)
                                                    {
                                                        serverVessels_InPresent[vessel_update.id] = true;
                                                        foreach (Part part in extant_vessel.Parts)
                                                        {
                                                            part.setOpacity(1f);
                                                        }
                                                    }

                                                    //Update rotation
                                                    if (extant_vessel.loaded)
                                                    {
                                                        extant_vessel.transform.up = vessel.worldDirection;
                                                        Quaternion rot = new Quaternion(vessel_update.rot[0],vessel_update.rot[1],vessel_update.rot[2],vessel_update.rot[3]);
                                                        extant_vessel.SetRotation(rot);
                                                        extant_vessel.angularMomentum = Vector3.zero;
                                                        extant_vessel.VesselSAS.LockHeading(rot);
                                                        extant_vessel.VesselSAS.currentRotation = rot;
                                                        extant_vessel.VesselSAS.SetDampingMode(false);
                                                    }

                                                    if (!KMPVessel.situationIsOrbital(vessel_update.situation) || extant_vessel.altitude < 10000f || ourDistance > 2500f)
                                                    {
                                                        KMPClientMain.DebugLog ("velocity update");
                                                        //Update velocity
                                                        if (extant_vessel.loaded)
                                                        {
                                                            if (update_body.GetAltitude(vessel.worldPosition)<10000d)
                                                            {
                                                                //Set velocity by surface velocity
                                                                Vector3d new_srf_vel = new Vector3d(vessel_update.s_vel[0],vessel_update.s_vel[1],vessel_update.s_vel[2]);
                                                                if (new_srf_vel.sqrMagnitude>1d) extant_vessel.ChangeWorldVelocity((-1 * extant_vessel.srf_velocity) + new_srf_vel);
                                                                else extant_vessel.ChangeWorldVelocity(-0.99f * extant_vessel.srf_velocity);
                                                            }
                                                            else
                                                            {
                                                                //Set velocity by orbit velocity
                                                                Vector3d new_obt_vel = new Vector3d(vessel_update.o_vel[0],vessel_update.o_vel[1],vessel_update.o_vel[2]);
                                                                if (new_obt_vel.sqrMagnitude>1d) extant_vessel.ChangeWorldVelocity((-1 * extant_vessel.obt_velocity) + new_obt_vel);
                                                                else extant_vessel.ChangeWorldVelocity(-0.99f * extant_vessel.obt_velocity);
                                                            }
                                                        }

                                                        //Update position
                                                        if (extant_vessel.altitude < 10000f || !extant_vessel.loaded)
                                                        {
                                                            if (extant_vessel.loaded && (vessel_update.situation == Situation.LANDED || vessel_update.situation == Situation.SPLASHED))
                                                            {
                                                                //Update surface position
                                                                KMPClientMain.DebugLog("surface position update");
                                                                Vector3d newPos = update_body.GetWorldSurfacePosition(vessel_update.w_pos[1],vessel_update.w_pos[2],extant_vessel.altitude+0.001d);
                                                                if ((newPos - extant_vessel.GetWorldPos3D()).sqrMagnitude > 1d)
                                                                    extant_vessel.SetPosition(newPos);
                                                                else if (Vector3.Distance(vessel.worldPosition, extant_vessel.GetWorldPos3D()) > 25f)
                                                                {
                                                                    serverVessels_PartCounts[vessel_update.id] = 0;
                                                                    addRemoteVessel(protovessel,vessel_update.id,vessel_update);
                                                                }
                                                            }
                                                            else if (!throttled && Vector3.Distance(vessel.worldPosition, extant_vessel.GetWorldPos3D()) > 1d
                                                                     && (extant_vessel.altitude < 10000f || ourDistance > 3000f)
                                                                     && update_body.GetAltitude(vessel.worldPosition) > 1d)
                                                            {
                                                                //Update 3D position
                                                                KMPClientMain.DebugLog("position update");
                                                                extant_vessel.SetPosition(vessel.worldPosition);
                                                            }
                                                            else if (!extant_vessel.loaded && ourDistance > 1000 && update_body.GetAltitude(vessel.worldPosition) > 1d)
                                                            {
                                                                //Stretch packing thresholds to prevent excessive load/unloads during rendezvous initiation
                                                                extant_vessel.distancePackThreshold += 250f;
                                                                extant_vessel.distanceUnpackThreshold += 100f;
                                                            } else
                                                            {
                                                                //Reset packing thresholds
                                                                extant_vessel.distancePackThreshold = 7500f;
                                                                extant_vessel.distanceUnpackThreshold = 1000f;
                                                            }
                                                        }

                                                        //Update FlightCtrlState
                                                        extant_vessel.ctrlState.CopyFrom(vessel_update.flightCtrlState.getAsFlightCtrlState(0.75f));
                                                    }
                                                    else
                                                    {
                                                        //Orbital rendezvous
                                                        KMPClientMain.DebugLog("orbital rendezvous");

                                                        //Update FlightCtrlState
                                                        extant_vessel.ctrlState.CopyFrom(vessel_update.flightCtrlState.getAsFlightCtrlState(0.6f));
                                                    }
                                                }
                                                else if (FlightGlobals.ActiveVessel.mainBody == vessel.mainBody)
                                                {
                                                    KMPClientMain.DebugLog("update from past/future");

                                                    if (!serverVessels_InPresent.ContainsKey(vessel_update.id) || serverVessels_InPresent.ContainsKey(vessel_update.id) ? serverVessels_InPresent[vessel_update.id]: false)
                                                    {
                                                        serverVessels_InPresent[vessel_update.id] = false;
                                                        foreach (Part part in extant_vessel.Parts)
                                                        {
                                                            part.setOpacity(0.3f);
                                                        }
                                                    }

                                                    //Update rotation only
                                                    extant_vessel.transform.up = vessel.worldDirection;
                                                    extant_vessel.SetRotation(new Quaternion(vessel_update.rot[0],vessel_update.rot[1],vessel_update.rot[2],vessel_update.rot[3]));
                                                }
                                            }
                                        }
                                        KMPClientMain.DebugLog("updated");
                                    }
                                    else
                                    {
                                        //Update flag if needed
                                        if (vessel_update.getProtoVesselNode() != null)
                                        {
                                            ProtoVessel protovessel = new ProtoVessel(serverVessels_ProtoVessels[vessel_update.id], HighLogic.CurrentGame);
                                            addRemoteVessel(protovessel,vessel_update.id,vessel_update);
                                        }
                                    }
                                }
                                else
                                {
                                    try
                                    {
                                        if (serverVessels_ProtoVessels.ContainsKey(vessel_update.id))
                                        {
                                            KMPClientMain.DebugLog("Adding new vessel: " + vessel_update.id);
                                            ProtoVessel protovessel = new ProtoVessel(serverVessels_ProtoVessels[vessel_update.id], HighLogic.CurrentGame);
                                            if (vessel.orbitValid && KMPVessel.situationIsOrbital(vessel_update.situation) && protovessel.vesselType != VesselType.Flag && protovessel.vesselType != VesselType.EVA)
                                            {
                                                protovessel = syncOrbit(vessel, vessel_update.tick, protovessel, vessel_update.w_pos[0]);
                                            }
                                            serverVessels_PartCounts[vessel_update.id] = 0;
                                            addRemoteVessel(protovessel, vessel_update.id, vessel_update, incomingDistance);
                                            HighLogic.CurrentGame.CrewRoster.ValidateAssignments(HighLogic.CurrentGame);
                                        }
                                        else
                                        {
                                            KMPClientMain.DebugLog("New vessel, but no matching protovessel available");
                                        }
                                    } catch (Exception e) { KMPClientMain.DebugLog("Vessel add error: " + e.Message + "\n" + e.StackTrace); }
                                }
                            }
                            else
                            {
                                KMPClientMain.DebugLog("Vessel update ignored: we are closer to target vessel or have recently updated from someone who was closer");
                            }
                        }
                        else
                        {
                            KMPClientMain.DebugLog("Vessel update ignored: target vessel on load delay list");
                        }
                    }
                }
                else
                {
                    //This is our vessel!
                    if (vessel_update.getProtoVesselNode() != null && docking)
                    {
                        KMPClientMain.DebugLog("Received updated protovessel for active vessel");
                        serverVessels_ProtoVessels[vessel_update.id] = vessel_update.getProtoVesselNode();
                    }

                    if (vessel_update.isDockUpdate && vessel_update.relTime == RelativeTime.PRESENT)
                    {
                        //Someone docked with us and has control
                        docking = true;
                        syncing = true;
                        ScreenMessages.PostScreenMessage("Other player has control of newly docked vessel",2.5f,ScreenMessageStyle.UPPER_LEFT);
                        KMPClientMain.DebugLog("Received docking update");
                        serverVessels_PartCounts[FlightGlobals.ActiveVessel.id] = 0;

                        //Return to tracking station
                        Invoke("dockedKickToTrackingStation",0.25f);
                        return;
                    }
                    //Try to negotiate our relative position with whatever sent this update
                    if (FlightGlobals.ActiveVessel.altitude > 10000d && vessel_update.relativeTo != Guid.Empty && Math.Abs(Planetarium.GetUniversalTime() - vessel_update.tick) < 2d)
                    {
                        Vessel updateFrom = FlightGlobals.Vessels.Find (v => v.id == vessel_update.relativeTo);
                        if (updateFrom != null && !updateFrom.loaded)
                        {
                            KMPClientMain.DebugLog("Rendezvous update from unloaded vessel");
                            if (vessel_update.distance < INACTIVE_VESSEL_RANGE)
                            {
                                //We're not in normal secondary vessel range but other vessel is, send negotiating reply
                                KMPVesselUpdate update = getVesselUpdate(updateFrom);
                                update.distance = INACTIVE_VESSEL_RANGE;
                                update.state = State.INACTIVE;
                                //Rendezvous relative position data
                                update.relativeTo = FlightGlobals.ActiveVessel.id;
                                Vector3d w_pos = updateFrom.findWorldCenterOfMass() - activeVesselPosition;
                                Vector3d o_vel = updateFrom.GetObtVelocity() - FlightGlobals.ActiveVessel.GetObtVelocity();
                                for (int i = 0; i < 3; i++)
                                {
                                    update.w_pos[i] = w_pos[i];
                                    update.o_vel[i] = o_vel[i];
                                }

                                byte[] update_bytes = KSP.IO.IOUtils.SerializeToBinary(update);
                                enqueuePluginInteropMessage(KMPCommon.PluginInteropMessageID.SECONDARY_PLUGIN_UPDATE, update_bytes);

                                //updateFrom.distancePackThreshold += INACTIVE_VESSEL_RANGE/2;
                            }
                        }
                        else if (updateFrom != null && updateFrom.loaded)
                        {
                            KMPClientMain.DebugLog("rendezvous positioning: " + updateFrom.id);

                            Vector3d updateFromPos = updateFrom.findWorldCenterOfMass();
                            Vector3d relPos = activeVesselPosition-updateFromPos;
                            Vector3d updateRelPos = new Vector3d(vessel_update.w_pos[0],vessel_update.w_pos[1],vessel_update.w_pos[2]);

                            if (!dockingRelVel.ContainsKey(updateFrom.id))
                                dockingRelVel[updateFrom.id] = updateFrom.GetObtVelocity();

                            Vector3d relVel = FlightGlobals.ActiveVessel.GetObtVelocity()-dockingRelVel[updateFrom.id];
                            Vector3d updateRelVel = new Vector3d(vessel_update.o_vel[0],vessel_update.o_vel[1],vessel_update.o_vel[2]);
                            Vector3d diffPos = updateRelPos - relPos;
                            Vector3d diffVel = updateRelVel - relVel;
                            diffPos *= 0.45d;
                            diffVel *= 0.45d;
                            Vector3d newPos = updateFromPos-diffPos;

                            bool applyUpdate = true;
                            double curTick = Planetarium.GetUniversalTime();
                            if (serverVessels_RendezvousSmoothPos.ContainsKey(updateFrom.id) ? (relPos.sqrMagnitude > (serverVessels_RendezvousSmoothPos[updateFrom.id].Key * 25) && serverVessels_RendezvousSmoothPos[updateFrom.id].Value > (curTick-5d)): false)
                                applyUpdate = false;
                            if (serverVessels_RendezvousSmoothVel.ContainsKey(updateFrom.id) ? (relVel.sqrMagnitude > (serverVessels_RendezvousSmoothVel[updateFrom.id].Key * 25) && serverVessels_RendezvousSmoothVel[updateFrom.id].Value > (curTick-5d)): false)
                                applyUpdate = false;

                            double expectedDist = Vector3d.Distance(newPos, activeVesselPosition);

                            if (applyUpdate)
                            {
                                serverVessels_RendezvousSmoothPos[updateFrom.id] = new KeyValuePair<double, double>(diffPos.sqrMagnitude,curTick);
                                serverVessels_RendezvousSmoothVel[updateFrom.id] = new KeyValuePair<double, double>(diffVel.sqrMagnitude,curTick);

                                try
                                {
                                    OrbitPhysicsManager.HoldVesselUnpack(1);
                                }
                                catch (NullReferenceException)
                                {
                                }

                                if (diffPos.sqrMagnitude < 1000000d && diffPos.sqrMagnitude > 0.5d)
                                {
                                    KMPClientMain.DebugLog("Docking Krakensbane shift");
                                    foreach (Vessel otherVessel in FlightGlobals.Vessels.Where(v => v.packed == false && v.id != FlightGlobals.ActiveVessel.id && v.id == updateFrom.id))
                                        otherVessel.GoOnRails();
                                    getKrakensbane().setOffset(diffPos);
                                }
                                else if (diffPos.sqrMagnitude >= 1000000d)
                                {
                                    KMPClientMain.DebugLog("Clamped docking Krakensbane shift");
                                    diffPos.Normalize();
                                    diffPos *= 1000d;
                                    foreach (Vessel otherVessel in FlightGlobals.Vessels.Where(v => v.packed == false && v.id != FlightGlobals.ActiveVessel.id))
                                        otherVessel.GoOnRails();
                                    getKrakensbane().setOffset(diffPos);
                                }

                                activeVesselPosition += diffPos;

                                if (diffVel.sqrMagnitude > 0.0025d && diffVel.sqrMagnitude < 2500d)
                                {
                                    KMPClientMain.DebugLog("Docking velocity update");
                                    if (updateFrom.packed) updateFrom.GoOffRails();
                                    updateFrom.ChangeWorldVelocity(-diffVel);
                                }
                                else if (diffVel.sqrMagnitude >= 2500d)
                                {
                                    KMPClientMain.DebugLog("Damping large velocity differential");
                                    diffVel = diffVel.normalized;
                                    diffVel *= 50d;
                                    if (updateFrom.packed) updateFrom.GoOffRails();
                                    updateFrom.ChangeWorldVelocity(-diffVel);
                                }

                                dockingRelVel[updateFrom.id] -= diffVel;

                                KMPClientMain.DebugLog("had dist:" + relPos.magnitude + " got dist:" + updateRelPos.magnitude);
                                KMPClientMain.DebugLog("expected dist:" + expectedDist + " diffPos mag: " + diffPos.sqrMagnitude);
                                KMPClientMain.DebugLog("had relVel:" + relVel.magnitude + " got relVel:" + updateRelVel.magnitude + " diffVel mag:" + diffVel.sqrMagnitude);
                            }
                        }  else KMPClientMain.DebugLog("Ignored docking position update: unexpected large pos/vel shift");
                    } else KMPClientMain.DebugLog("Ignored docking position update: " + (FlightGlobals.ActiveVessel.altitude > 10000d) + " " + (vessel_update.relativeTo != Guid.Empty) + " " + (Math.Abs(Planetarium.GetUniversalTime() - vessel_update.tick) < 1d));
                }
            }
        }
Example #6
0
        private void applyVesselUpdate(KLFVesselUpdate vessel_update, KLFVessel vessel)
        {
            //Find the CelestialBody that matches the one in the update
            CelestialBody update_body = null;

            if (vessel.mainBody != null && vessel.mainBody.bodyName == vessel_update.bodyName)
                update_body = vessel.mainBody; //Vessel already has the correct body
            else
            {

                //Find the celestial body in the list of bodies
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    if (body.bodyName == vessel_update.bodyName)
                    {
                        update_body = body;
                        break;
                    }
                }

            }

            if (update_body != null)
            {

                //Convert float arrays to Vector3s
                Vector3 pos = new Vector3(vessel_update.pos[0], vessel_update.pos[1], vessel_update.pos[2]);
                Vector3 dir = new Vector3(vessel_update.dir[0], vessel_update.dir[1], vessel_update.dir[2]);
                Vector3 vel = new Vector3(vessel_update.vel[0], vessel_update.vel[1], vessel_update.vel[2]);

                vessel.info = vessel_update;
                vessel.setOrbitalData(update_body, pos, vel, dir);

            }

            if (vessel_update.state == State.ACTIVE)
            {
                //Update the player status info
                VesselStatusInfo status = new VesselStatusInfo();
                status.info = vessel_update;
                status.ownerName = vessel_update.player;
                status.vesselName = vessel_update.name;

                if (vessel.orbitValid)
                    status.orbit = vessel.orbitRenderer.driver.orbit;

                status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                status.color = KLFVessel.generateActiveColor(status.ownerName);

                if (playerStatus.ContainsKey(status.ownerName))
                    playerStatus[status.ownerName] = status;
                else
                    playerStatus.Add(status.ownerName, status);
            }
        }
Example #7
0
        private void handleVesselUpdate(KLFVesselUpdate vessel_update)
        {
            if (!isInFlight)
            {
                //While not in-flight don't create KLF vessel, just store the active vessel status info
                if (vessel_update.state == State.ACTIVE) {

                    VesselStatusInfo status = new VesselStatusInfo();
                    status.info = vessel_update;
                    status.ownerName = vessel_update.player;
                    status.vesselName = vessel_update.name;
                    status.orbit = null;
                    status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                    status.color = KLFVessel.generateActiveColor(status.ownerName);

                    if (playerStatus.ContainsKey(status.ownerName))
                        playerStatus[status.ownerName] = status;
                    else
                        playerStatus.Add(status.ownerName, status);
                }

                return; //Don't handle updates while not flying a ship
            }

            //Build the key for the vessel
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append(vessel_update.player);
            sb.Append(vessel_update.id.ToString());

            String vessel_key = sb.ToString();

            KLFVessel vessel = null;

            //Try to find the key in the vessel dictionary
            VesselEntry entry;
            if (vessels.TryGetValue(vessel_key, out entry))
            {
                vessel = entry.vessel;

                if (vessel == null || vessel.gameObj == null || vessel.vesselName != vessel_update.name)
                {
                    //Delete the vessel if it's null or needs to be renamed
                    vessels.Remove(vessel_key);

                    if (vessel != null && vessel.gameObj != null)
                        GameObject.Destroy(vessel.gameObj);

                    vessel = null;
                }
                else
                {
                    //Update the entry's timestamp
                    VesselEntry new_entry = new VesselEntry();
                    new_entry.vessel = entry.vessel;
                    new_entry.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;

                    vessels[vessel_key] = new_entry;
                }
            }

            if (vessel == null) {
                //Add the vessel to the dictionary
                vessel = new KLFVessel(vessel_update.name, vessel_update.player, vessel_update.id);
                entry = new VesselEntry();
                entry.vessel = vessel;
                entry.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;

                if (vessels.ContainsKey(vessel_key))
                    vessels[vessel_key] = entry;
                else
                    vessels.Add(vessel_key, entry);

                /*Queue this update for the next update call because updating a vessel on the same step as
                 * creating it usually causes problems for some reason */
                vesselUpdateQueue.Enqueue(vessel_update);
            }
            else
                applyVesselUpdate(vessel_update, vessel); //Apply the vessel update to the existing vessel
        }
Example #8
0
        private VesselStatusInfo statusArrayToInfo(String[] status_array)
        {
            if (status_array != null && status_array.Length >= STATUS_ARRAY_MIN_SIZE)
            {
                //Read status array
                VesselStatusInfo status = new VesselStatusInfo();
                status.info = null;
                status.ownerName = status_array[0];
                status.vesselName = status_array[1];

                if (status_array.Length >= 3)
                    status.detailText = status_array[2];

                status.orbit = null;
                status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                status.color = KLFVessel.generateActiveColor(status.ownerName);

                return status;
            }
            else
                return new VesselStatusInfo();
        }
Example #9
0
        private void writePrimaryUpdate()
        {
            if (isInFlight)
            {
                //Write vessel status
                KLFVesselUpdate update = getVesselUpdate(FlightGlobals.ActiveVessel);

                //Update the player vessel info
                VesselStatusInfo my_status = new VesselStatusInfo();
                my_status.info = update;
                my_status.orbit = FlightGlobals.ActiveVessel.orbit;
                my_status.color = KLFVessel.generateActiveColor(playerName);
                my_status.ownerName = playerName;
                my_status.vesselName = FlightGlobals.ActiveVessel.vesselName;
                my_status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;

                if (playerStatus.ContainsKey(playerName))
                    playerStatus[playerName] = my_status;
                else
                    playerStatus.Add(playerName, my_status);

                enqueuePluginInteropMessage(KLFCommon.PluginInteropMessageID.PRIMARY_PLUGIN_UPDATE, KSP.IO.IOUtils.SerializeToBinary(update));
            }
            else
            {
                //Check if the player is building a ship
                bool building_ship = HighLogic.LoadedSceneIsEditor
                    && EditorLogic.fetch != null
                    && EditorLogic.fetch.ship != null && EditorLogic.fetch.ship.Count > 0
                    && EditorLogic.fetch.shipNameField != null
                    && EditorLogic.fetch.shipNameField.Text != null && EditorLogic.fetch.shipNameField.Text.Length > 0;

                String[] status_array = null;

                if (building_ship)
                {
                    status_array = new String[3];

                    //Vessel name
                    String shipname = EditorLogic.fetch.shipNameField.Text;

                    if (shipname.Length > MAX_VESSEL_NAME_LENGTH)
                        shipname = shipname.Substring(0, MAX_VESSEL_NAME_LENGTH); //Limit vessel name length

                    status_array[1] = "Building " + shipname;

                    //Vessel details
                    status_array[2] = "Parts: " + EditorLogic.fetch.ship.Count;
                }
                else
                {
                    status_array = new String[2];

                    switch (HighLogic.LoadedScene)
                    {
                        case GameScenes.SPACECENTER:
                            status_array[1] = "At Space Center";
                            break;
                        case GameScenes.EDITOR:
                            status_array[1] = "In Vehicle Assembly Building";
                            break;
                        case GameScenes.SPH:
                            status_array[1] = "In Space Plane Hangar";
                            break;
                        case GameScenes.TRACKSTATION:
                            status_array[1] = "At Tracking Station";
                            break;
                        default:
                            status_array[1] = String.Empty;
                            break;
                    }
                }

                //Check if player is idle
                if (isIdle)
                    status_array[1] = "(Idle) " + status_array[1];

                status_array[0] = playerName;

                //Serialize the update
                byte[] update_bytes = KSP.IO.IOUtils.SerializeToBinary(status_array);

                enqueuePluginInteropMessage(KLFCommon.PluginInteropMessageID.PRIMARY_PLUGIN_UPDATE, update_bytes);

                VesselStatusInfo my_status = statusArrayToInfo(status_array);
                if (playerStatus.ContainsKey(playerName))
                    playerStatus[playerName] = my_status;
                else
                    playerStatus.Add(playerName, my_status);
            }
        }
Example #10
0
        private void ApplyVesselUpdate(KLFVesselUpdate vesselUpdate, KLFVessel kVes)
        {
            //Find the CelestialBody that matches the one in the update
            CelestialBody updateBody = null;
            if(kVes.MainBody != null
            && kVes.MainBody.bodyName == vesselUpdate.BodyName)
                updateBody = kVes.MainBody; //already correct body
            else
                foreach (CelestialBody body in FlightGlobals.Bodies)
                    if (body.bodyName == vesselUpdate.BodyName)
                    {
                        updateBody = body;
                        break;
                    }

            if (updateBody != null)
            {//Convert float arrays to Vector3s
                Vector3 pos = new Vector3(vesselUpdate.Position[0], vesselUpdate.Position[1], vesselUpdate.Position[2]);
                Vector3 dir = new Vector3(vesselUpdate.Direction[0], vesselUpdate.Direction[1], vesselUpdate.Direction[2]);
                Vector3 vel = new Vector3(vesselUpdate.Velocity[0], vesselUpdate.Velocity[1], vesselUpdate.Velocity[2]);

                kVes.Info = vesselUpdate;
                kVes.SetOrbitalData(updateBody, pos, vel, dir);
            }

            if (vesselUpdate.State == State.Active)
            {//Update the player status info
                VesselStatusInfo status = new VesselStatusInfo();
                status.Info = vesselUpdate;
                status.User = vesselUpdate.Player;
                status.VesselName = vesselUpdate.Name;
                if (kVes.OrbitValid)
                    status.Orbit = kVes.OrbitRender.driver.orbit;
                status.LastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                status.Color = KLFVessel.GenerateActiveColor(status.User);

                if (PlayerStatus.ContainsKey(status.User))
                    PlayerStatus[status.User] = status;
                else
                    PlayerStatus.Add(status.User, status);
            }
        }
Example #11
0
        private void WritePrimaryUpdate()
        {
            if (IsInFlight)
            {
                //Write vessel status
                KLFVesselUpdate update = GetVesselUpdate(FlightGlobals.ActiveVessel);
                //Update the player vessel info
                VesselStatusInfo myStatus = new VesselStatusInfo();
                myStatus.Info = update;
                myStatus.Orbit = FlightGlobals.ActiveVessel.orbit;
                myStatus.Color = KLFVessel.GenerateActiveColor(PlayerName);
                myStatus.User = PlayerName;
                myStatus.VesselName = FlightGlobals.ActiveVessel.vesselName;
                myStatus.LastUpdateTime = UnityEngine.Time.realtimeSinceStartup;

                if (PlayerStatus.ContainsKey(PlayerName))
                    PlayerStatus[PlayerName] = myStatus;
                else
                    PlayerStatus.Add(PlayerName, myStatus);

                EnqueuePluginInteropMessage(KLFCommon.PluginInteropMessageID.PrimaryPluginUpdate
                        , KSP.IO.IOUtils.SerializeToBinary(update));
            }
            else
            {
                //Check if the player is building a ship
                bool buildingShip = HighLogic.LoadedSceneIsEditor
                                 && EditorLogic.fetch != null
                                 && EditorLogic.fetch.ship != null
                                 && EditorLogic.fetch.ship.Count > 0
                                 && EditorLogic.fetch.shipNameField != null
                                 && EditorLogic.fetch.shipNameField.Text != null
                                 && EditorLogic.fetch.shipNameField.Text.Length > 0;

                //build status line to send to other clients
                String[] statusArray = null;
                if (buildingShip)
                {
                    statusArray = new String[3];
                    //Vessel name
                    String shipname = EditorLogic.fetch.shipNameField.Text;
                    if (shipname.Length > MaxVesselNameLength)
                        shipname = shipname.Substring(0, MaxVesselNameLength);
                    statusArray[1] = "Building " + shipname;
                    //Vessel details
                    statusArray[2] = "Parts: " + EditorLogic.fetch.ship.Count;
                }
                else
                {
                    statusArray = new String[2];
                    switch (HighLogic.LoadedScene)
                    {
                    case GameScenes.SPACECENTER:
                        statusArray[1] = KSP_SC_Location;
                        break;
                    case GameScenes.EDITOR:
                        statusArray[1] = "In Vehicle Assembly Building";
                        break;
                    case GameScenes.TRACKSTATION:
                        statusArray[1] = "At Tracking Station";
                        break;
                    default:
                        statusArray[1] = String.Empty;
                        break;
                    }
                }

                //Check if player is idle
                if (IsIdle)
                    statusArray[1] = "(Idle) " + statusArray[1];
                statusArray[0] = PlayerName;

                //Serialize the update
                byte[] updateBytes = KSP.IO.IOUtils.SerializeToBinary(statusArray);
                EnqueuePluginInteropMessage(KLFCommon.PluginInteropMessageID.PrimaryPluginUpdate, updateBytes);

                VesselStatusInfo myStatus = StatusArrayToInfo(statusArray);
                if (PlayerStatus.ContainsKey(PlayerName))
                    PlayerStatus[PlayerName] = myStatus;
                else
                    PlayerStatus.Add(PlayerName, myStatus);
            }
        }
Example #12
0
        private void VesselStatusLabels(VesselStatusInfo status, bool big)
        {
            bool namePressed = false;
            PlayerNameStyle.normal.textColor = status.Color * 0.75f + Color.white * 0.25f;

            if (big)
                GUILayout.BeginHorizontal();
            if (status.User != null)
                namePressed |= GUILayout.Button(status.User, PlayerNameStyle);
            if (status.VesselName != null && status.VesselName.Length > 0)
            {
                String vName = status.VesselName;
                if (status.Info != null && status.Info.Detail != null && status.Info.Detail.Idle)
                    vName = "(Idle) " + vName;
                namePressed |= GUILayout.Button(vName, VesselNameStyle);
            }

            if (big)
                GUILayout.EndHorizontal();

            //Build the detail text
            StringBuilder sb = new StringBuilder();

            //Check if the status has specific detail text
            if (status.DetailText != null && status.DetailText.Length > 0 && KLFInfoDisplay.InfoDisplayDetailed)
                sb.Append(status.DetailText);
            else if (status.Info != null && status.Info.Detail != null)
            {

                bool exploded = false;
                bool situationDetermined = false;

                if(status.Info.Situation == Situation.Destroyed
                || status.Info.Detail.Mass <= 0.0f)
                {
                    sb.Append("Exploded at ");
                    exploded = true;
                    situationDetermined = true;
                }
                else
                {
                    //Check if the vessel's activity overrides the situation
                    switch (status.Info.Detail.Activity)
                    {
                    case Activity.Aerobraking:
                        sb.Append("Aerobraking at ");
                        situationDetermined = true;
                        break;
                    case Activity.Docking:
                        if (KLFVessel.SituationIsGrounded(status.Info.Situation))
                            sb.Append("Docking on ");
                        else
                            sb.Append("Docking above ");
                        situationDetermined = true;
                        break;
                    case Activity.Parachuting:
                        sb.Append("Parachuting to ");
                        situationDetermined = true;
                        break;
                    }

                    if (!situationDetermined)
                    {
                        switch (status.Info.Situation)
                        {
                        case Situation.Docked:
                            sb.Append("Docked at ");
                            break;
                        case Situation.Encountering:
                            sb.Append("Encountering ");
                            break;
                        case Situation.Escaping:
                            sb.Append("Escaping ");
                            break;
                        case Situation.Flying:
                            sb.Append("Flying at ");
                            break;
                        case Situation.Landed:
                            sb.Append("Landed at ");
                            break;
                        case Situation.Orbiting:
                            sb.Append("Orbiting ");
                            break;
                        case Situation.Prelaunch:
                            sb.Append("Prelaunch at ");
                            break;
                        case Situation.Splashed:
                            sb.Append("Splashed at ");
                            break;
                        case Situation.Ascending:
                            sb.Append("Ascending from ");
                            break;
                        case Situation.Descending:
                            sb.Append("Descending to ");
                            break;
                        }
                    }
                }

                sb.Append(status.Info.BodyName);
                if (!exploded && KLFInfoDisplay.InfoDisplayDetailed)
                {

                    bool showMass = status.Info.Detail.Mass >= 0.05f;
                    bool showFuel = status.Info.Detail.FuelPercent < byte.MaxValue;
                    bool showRcs = status.Info.Detail.RcsPercent < byte.MaxValue;
                    bool showCrew = status.Info.Detail.CrewCount < byte.MaxValue;

                    if (showMass || showFuel || showRcs || showCrew)
                        sb.Append(" - ");
                    if (showMass)
                    {
                        sb.Append("Mass: ");
                        sb.Append(status.Info.Detail.Mass.ToString("0.0"));
                        sb.Append(' ');
                    }
                    if (showFuel)
                    {
                        sb.Append("Fuel: ");
                        sb.Append(status.Info.Detail.FuelPercent);
                        sb.Append("% ");
                    }
                    if (showRcs)
                    {
                        sb.Append("RCS: ");
                        sb.Append(status.Info.Detail.RcsPercent);
                        sb.Append("% ");
                    }
                    if (showCrew)
                    {
                        sb.Append("Crew: ");
                        sb.Append(status.Info.Detail.CrewCount);
                    }
                }
            }

            if (sb.Length > 0)
                GUILayout.Label(sb.ToString(), StateTextStyle);
            if (namePressed
            && HighLogic.LoadedSceneHasPlanetarium && PlanetariumCam != null
            && status.Info != null
            && status.Info.BodyName.Length > 0)
            {//If name was pressed, focus on that players' reference body
                if (!MapView.MapIsEnabled)
                    MapView.EnterMapView();
                foreach (MapObject target in PlanetariumCam.targets)
                {
                    if (target.name == status.Info.BodyName)
                    {
                        PlanetariumCam.SetTarget(target);
                        break;
                    }
                }
            }
        }
Example #13
0
 private VesselStatusInfo StatusArrayToInfo(String[] statusArray)
 {
     if (statusArray != null && statusArray.Length >= StatusArrayMinSize)
     {//Read status array
         VesselStatusInfo status = new VesselStatusInfo();
         status.Info = null;
         status.User = statusArray[0];
         status.VesselName = statusArray[1];
         if (statusArray.Length >= 3)
             status.DetailText = statusArray[2];
         status.Orbit = null;
         status.LastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
         status.Color = KLFVessel.GenerateActiveColor(status.User);
         return status;
     }
     else
         return new VesselStatusInfo();
 }
Example #14
0
        private void HandleVesselUpdate(KLFVesselUpdate vesselUpdate)
        {
            if (!IsInFlight)
            {
                //While not in-flight don't create KLF vessel, just store the active vessel status info
                if (vesselUpdate.State == State.Active)
                {
                    VesselStatusInfo status = new VesselStatusInfo();
                    status.Info = vesselUpdate;
                    status.User = vesselUpdate.Player;
                    status.VesselName = vesselUpdate.Name;
                    status.Orbit = null;
                    status.LastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                    status.Color = KLFVessel.GenerateActiveColor(status.User);
                    if (PlayerStatus.ContainsKey(status.User))
                        PlayerStatus[status.User] = status;
                    else
                        PlayerStatus.Add(status.User, status);
                }
                return; //Don't handle updates while not flying a ship
            }

            //Build the key for the vessel
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append(vesselUpdate.Player);
            sb.Append(vesselUpdate.Id.ToString());

            String vesselKey = sb.ToString();
            KLFVessel kVes = null;

            //Try to find the key in the vessel dictionary
            VesselEntry entry;
            if (Vessels.TryGetValue(vesselKey, out entry))
            {
                kVes = entry.Vessel;
                if(kVes == null
                || kVes.GameObj == null
                || kVes.VesselName != vesselUpdate.Name)
                {//Delete the vessel if it's null or needs to be renamed
                    Vessels.Remove(vesselKey);
                    if (kVes != null && kVes.GameObj != null)
                        GameObject.Destroy(kVes.GameObj);
                    kVes = null;
                }
                else
                {
                    //Update the entry's timestamp
                    VesselEntry newEntry = new VesselEntry();
                    newEntry.Vessel = entry.Vessel;
                    newEntry.LastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                    Vessels[vesselKey] = newEntry;
                }
            }

            if (kVes == null)
            {//Add the vessel to the dictionary
                kVes = new KLFVessel(vesselUpdate.Name, vesselUpdate.Player, vesselUpdate.Id);
                entry = new VesselEntry();
                entry.Vessel = kVes;
                entry.LastUpdateTime = UnityEngine.Time.realtimeSinceStartup;

                if (Vessels.ContainsKey(vesselKey))
                    Vessels[vesselKey] = entry;
                else
                    Vessels.Add(vesselKey, entry);

                /*Queue this update for the next update call because updating a vessel on the same step as
                 * creating it usually causes problems for some reason */
                VesselUpdateQueue.Enqueue(vesselUpdate);
            }
            else
                ApplyVesselUpdate(vesselUpdate, kVes); //Apply the vessel update to the existing vessel
        }