Exemplo n.º 1
0
        // return name of file being relayed, in case multiple ones are relayed the first one is returned
        public static string relaying(Vessel v, HashSet <Guid> avoid_inf_recursion)
        {
            foreach (Vessel w in FlightGlobals.Vessels)
            {
                // do not test with itself
                if (v == w)
                {
                    continue;
                }

                // skip vessels already in this chain
                if (avoid_inf_recursion.Contains(w.id))
                {
                    continue;
                }

                // get vessel info from cache
                // - if vessel is not already in cache, just ignore it
                vessel_info wi;
                if (!Cache.HasVesselInfo(w, out wi))
                {
                    continue;
                }

                // skip invalid vessels
                if (!wi.is_valid)
                {
                    continue;
                }

                // the vessel is relaying if at least another one that is using it as relay is transmitting data
                if (wi.transmitting.Length > 0 && wi.connection.path.Contains(v))
                {
                    return(wi.transmitting);
                }
            }
            return(string.Empty);
        }
Exemplo n.º 2
0
        public static ConnectionInfo connection(Vessel v, Vector3d position, AntennaInfo antenna, bool blackout, HashSet <Guid> avoid_inf_recursion)
        {
            // if signal mechanic is disabled, use RemoteTech/CommNet/S4
            if (!Features.Signal)
            {
                return(OtherComms(v));
            }

            // if it has no antenna
            if (antenna.no_antenna)
            {
                return(new ConnectionInfo(LinkStatus.no_antenna));
            }

            // if there is a storm and the vessel is inside a magnetosphere
            if (blackout)
            {
                return(new ConnectionInfo(LinkStatus.blackout));
            }

            // store raytracing data
            Vector3d dir;
            double   dist;
            bool     visible;

            // store other data
            double rate;
            List <ConnectionInfo> connections = new List <ConnectionInfo>();

            // raytrace home body
            visible = Sim.RaytraceBody(v, position, FlightGlobals.GetHomeBody(), out dir, out dist);

            // get rate
            rate = antenna.direct_rate(dist);

            // if directly linked
            if (visible && rate > Settings.ControlRate)
            {
                ConnectionInfo conn = new ConnectionInfo(LinkStatus.direct_link, rate, antenna.direct_cost);
                connections.Add(conn);
            }

            // for each other vessel
            foreach (Vessel w in FlightGlobals.Vessels)
            {
                // do not test with itself
                if (v == w)
                {
                    continue;
                }

                // skip vessels already in this chain
                if (avoid_inf_recursion.Contains(w.id))
                {
                    continue;
                }

                // get vessel from the cache
                // - when:
                //   . cache is empty (eg: new savegame loaded)
                // - we avoid single-tick wrong paths arising from this situation:
                //   . vessel A is directly linked
                //   . vessel B is indirectly linked through A
                //   . cache is cleared (after loading a savegame)
                //   . cache of A is computed
                //   . in turn, cache of B is computed ignoring A (and stored)
                //   . until cache of B is re-computed, B will result incorrectly not linked
                // - in this way:
                //   . cache of A is computed
                //   . in turn, cache of B is computed ignoring A (but not stored)
                //   . cache of B is then computed correctly
                //   . do not degenerate into O(N^3) by using non-optimal path
                vessel_info wi;
                if (!Cache.HasVesselInfo(w, out wi))
                {
                    if (connections.Count > 0)
                    {
                        continue;
                    }
                    else
                    {
                        wi = new vessel_info(w, Lib.VesselID(w), 0);
                    }
                }

                // skip invalid vessels
                if (!wi.is_valid)
                {
                    continue;
                }

                // skip non-relays and non-linked relays
                if (!wi.antenna.is_relay || !wi.connection.linked)
                {
                    continue;
                }

                // raytrace the other vessel
                visible = Sim.RaytraceVessel(v, w, position, Lib.VesselPosition(w), out dir, out dist);

                // get rate
                rate = antenna.indirect_rate(dist, wi.antenna);

                // if indirectly linked
                // - relays with no EC have zero relay_range
                // - avoid relay loops
                if (visible && rate > Settings.ControlRate && !wi.connection.path.Contains(v))
                {
                    // create indirect link data
                    ConnectionInfo conn = new ConnectionInfo(wi.connection);

                    // update the link data and return it
                    conn.status = LinkStatus.indirect_link;
                    conn.rate   = Math.Min(conn.rate, rate);
                    conn.cost   = antenna.indirect_cost;
                    conn.path.Add(w);
                    connections.Add(conn);
                }
            }

            // if at least a connection has been found
            if (connections.Count > 0)
            {
                // select the best connection
                double best_rate  = 0.0;
                int    best_index = 0;
                for (int i = 0; i < connections.Count; ++i)
                {
                    if (connections[i].rate > best_rate)
                    {
                        best_rate  = connections[i].rate;
                        best_index = i;
                    }
                }

                // and return it
                return(connections[best_index]);
            }

            // no link
            return(new ConnectionInfo(LinkStatus.no_link));
        }