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