예제 #1
0
        /// <summary> Creates a <see cref="ConnectionInfo"/> object for the specified vessel from it's antenna modules</summary>
        private ConnectionInfo(Vessel v, bool powered, bool storm)
        {
            // return no connection if there is no ec left
            if (!powered)
            {
                return;
            }

            AntennaInfo ai = GetAntennaInfo(v, powered, storm);

            ec           = ai.ec;
            rate         = ai.rate * PreferencesScience.Instance.transmitFactor;
            linked       = ai.linked;
            strength     = ai.strength;
            target_name  = ai.target_name;
            control_path = ai.control_path;

            switch (ai.status)
            {
            case 0: status = LinkStatus.direct_link; break;

            case 1: status = LinkStatus.indirect_link; break;

            case 2: status = LinkStatus.no_link; break;

            case 3: status = LinkStatus.plasma; break;

            case 4: status = LinkStatus.storm; break;

            default: status = LinkStatus.no_link; break;
            }
        }
예제 #2
0
        private static AntennaInfo GetAntennaInfo(Vessel v, bool powered, bool storm)
        {
            AntennaInfo ai = new AntennaInfo();

            ai.powered      = powered;
            ai.storm        = storm;
            ai.transmitting = !string.IsNullOrEmpty(Science.Transmitting(v, true));

            API.Comm.Init(ai, v);
            if (ai.strength > -1)
            {
                return(ai);
            }

            // if CommNet is enabled
            if (HighLogic.fetch.currentGame.Parameters.Difficulty.EnableCommNet)
            {
                return(new AntennaInfoCommNet(v, powered, storm, ai.transmitting));
            }

            // default: the simple stupid always connected signal system
            AntennaInfoCommNet antennaInfo = new AntennaInfoCommNet(v, powered, storm, ai.transmitting);

            antennaInfo.ec         *= 0.16;
            antennaInfo.linked      = true;
            antennaInfo.status      = (int)LinkStatus.direct_link;
            antennaInfo.strength    = 1;             // 100 %
            antennaInfo.target_name = "DSN: KSC";

            return(antennaInfo);
        }
예제 #3
0
        public static void RTCommInfoHandler(AntennaInfo antennaInfo, Vessel v)
        {
            var ai = new AntennaInfoRT(v, antennaInfo.powered, antennaInfo.storm);

            antennaInfo.linked       = ai.linked;
            antennaInfo.ec           = ai.ec;
            antennaInfo.control_path = ai.control_path;
            antennaInfo.rate         = ai.rate;
            antennaInfo.status       = ai.status;
            antennaInfo.strength     = ai.strength;
            antennaInfo.target_name  = ai.target_name;
        }
예제 #4
0
 //This initializes an antennaInfo object. Connection info handlers must
 //set antennaInfo.strength to a value >= 0, otherwise the antennaInfo will
 //be passed to the next handler.
 public void Init(AntennaInfo antennaInfo, Vessel pv)
 {
     //Loop through the list of listening methods and Invoke them.
     foreach (MethodInfo handler in handlers)
     {
         try {
             handler.Invoke(null, new object[] { antennaInfo, pv });
             if (antennaInfo.strength > -1)
             {
                 return;
             }
         } catch (Exception e) {
             Lib.Log("CommInfo handler threw exception " + e.Message + "\n" + e.ToString());
         }
     }
 }
예제 #5
0
        override public AntennaInfo AntennaInfo()
        {
            AntennaInfo result = base.AntennaInfo();

            result.ec      = 0;
            result.rate    = 0;
            result.powered = cluster.IsPowered;
            if (result.powered)
            {
                result.rate = Settings.DataRateSurfaceExperiment;
            }

            Init();

            return(result);
        }
        /// <summary> Creates a <see cref="ConnectionInfo"/> object for the specified vessel from it's antenna modules</summary>
        private ConnectionInfo(Vessel v, bool powered, bool storm)
        {
            // return no connection if there is no ec left
            if (!powered)
            {
                return;
            }

            // wait until network is initialized (2 seconds after load)
            if (!Communications.NetworkInitialized)
            {
                return;
            }

            AntennaInfo ai = GetAntennaInfo(v, powered, storm);

            ec           = SanityCheck(ai.ec, "ec", v);
            ec_idle      = SanityCheck(ai.ec_idle, "ec_idle", v);
            rate         = SanityCheck(ai.rate, "rate", v) * PreferencesScience.Instance.transmitFactor;
            linked       = ai.linked;
            strength     = SanityCheck(ai.strength, "strength", v);
            target_name  = ai.target_name;
            control_path = ai.control_path;

            switch (ai.status)
            {
            case 0: status = LinkStatus.direct_link; break;

            case 1: status = LinkStatus.indirect_link; break;

            case 2: status = LinkStatus.no_link; break;

            case 3: status = LinkStatus.plasma; break;

            case 4: status = LinkStatus.storm; break;

            default: status = LinkStatus.no_link; break;
            }
        }
        private static AntennaInfo GetAntennaInfo(Vessel v, bool powered, bool storm)
        {
            AntennaInfo ai = new AntennaInfo();

            ai.powered      = powered;
            ai.storm        = storm;
            ai.transmitting = v.KerbalismData().filesTransmitted.Count > 0;

            API.Comm.Init(ai, v);
            if (ai.strength > -1)
            {
                return(ai);
            }

            var cluster = Serenity.GetScienceCluster(v);

            if (cluster != null)
            {
                return(new AntennaInfoSerenity(v, cluster, storm, ai.transmitting).AntennaInfo());
            }

            // if CommNet is enabled
            if (HighLogic.fetch.currentGame.Parameters.Difficulty.EnableCommNet)
            {
                return(new AntennaInfoCommNet(v, powered, storm, ai.transmitting).AntennaInfo());
            }

            // default: the simple stupid always connected signal system
            AntennaInfo antennaInfo = new AntennaInfoCommNet(v, powered, storm, ai.transmitting).AntennaInfo();

            antennaInfo.ec         *= 0.16;
            antennaInfo.linked      = true;
            antennaInfo.status      = (int)LinkStatus.direct_link;
            antennaInfo.strength    = 1;             // 100 %
            antennaInfo.target_name = "DSN: KSC";

            return(antennaInfo);
        }
예제 #8
0
        public double indirect_rate(double d, AntennaInfo relay_antenna)
        {
            double r = 0.0;

            for (int i = 0; i < type.Count; ++i)
            {
                if (type[i] == AntennaType.low_gain)
                {
                    r += Antenna.calculate_rate(d, dist[i], rate[i]);
                }
            }

            double indirect_r = 0.0;

            for (int i = 0; i < relay_antenna.type.Count; ++i)
            {
                if (relay_antenna.type[i] == AntennaType.low_gain && relay_antenna.relay[i])
                {
                    indirect_r += Antenna.calculate_rate(d, relay_antenna.dist[i], relay_antenna.rate[i]);
                }
            }

            return(Math.Min(r, indirect_r));
        }
예제 #9
0
  public vessel_info(Vessel v, uint vessel_id, UInt64 inc)
  {
    // NOTE: anything used here can't in turn use cache, unless you know what you are doing

    // NOTE: you can't cache vessel position
    // at any point in time all vessel/body positions are relative to a different frame of reference
    // so comparing the current position of a vessel, with the cached one of another make no sense

    // associate with an unique incremental id
    this.inc = inc;

    // determine if this is a valid vessel
    is_vessel = Lib.IsVessel(v);
    if (!is_vessel) return;

    // determine if this is a rescue mission vessel
    is_rescue = Misc.IsRescueMission(v);
    if (is_rescue) return;

    // dead EVA are not valid vessels
    if (EVA.IsDead(v)) return;

    // shortcut for common tests
    is_valid = true;

    // generate id once
    id = vessel_id;

    // calculate crew info for the vessel
    crew_count = Lib.CrewCount(v);
    crew_capacity = Lib.CrewCapacity(v);

    // get vessel position
    Vector3d position = Lib.VesselPosition(v);

    // this should never happen again
    if (Vector3d.Distance(position, v.mainBody.position) < 1.0)
    {
      throw new Exception("Shit hit the fan for vessel " + v.vesselName);
    }

    // determine if in sunlight, calculate sun direction and distance
    sunlight = Sim.RaytraceBody(v, position, FlightGlobals.Bodies[0], out sun_dir, out sun_dist) ? 1.0 : 0.0;

    // at the two highest timewarp speed, the number of sun visibility samples drop to the point that
    // the quantization error first became noticeable, and then exceed 100%
    // to solve this, we switch to an analytical estimation of the portion of orbit that was in sunlight
    // - we check against timewarp rate, instead of index, to avoid issues during timewarp blending
    if (v.mainBody.flightGlobalsIndex != 0 && TimeWarp.CurrentRate > 1000.0f)
    {
      sunlight = 1.0 - Sim.ShadowPeriod(v) / Sim.OrbitalPeriod(v);
    }

    // environment stuff
    atmo_factor = Sim.AtmosphereFactor(v.mainBody, position, sun_dir);
    gamma_transparency = Sim.GammaTransparency(v.mainBody, v.altitude);
    underwater = Sim.Underwater(v);
    breathable = Sim.Breathable(v, underwater);
    landed = Lib.Landed(v);

    // temperature at vessel position
    temperature = Sim.Temperature(v, position, sunlight, atmo_factor, out solar_flux, out albedo_flux, out body_flux, out total_flux);
    temp_diff = Sim.TempDiff(temperature, v.mainBody, landed);

    // radiation
    radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out magnetosphere, out inner_belt, out outer_belt, out interstellar);

    // extended atmosphere
    thermosphere = Sim.InsideThermosphere(v);
    exosphere = Sim.InsideExosphere(v);

    // malfunction stuff
    malfunction = Reliability.HasMalfunction(v);
    critical = Reliability.HasCriticalFailure(v);

    // signal info
    antenna = new AntennaInfo(v);
    avoid_inf_recursion.Add(v.id);
    connection = Signal.connection(v, position, antenna, blackout, avoid_inf_recursion);
    transmitting = Science.transmitting(v, connection.linked);
    relaying = Signal.relaying(v, avoid_inf_recursion);
    avoid_inf_recursion.Remove(v.id);

    // habitat data
    volume = Habitat.tot_volume(v);
    surface = Habitat.tot_surface(v);
    pressure = Habitat.pressure(v);
    poisoning = Habitat.poisoning(v);
    shielding = Habitat.shielding(v);
    living_space = Habitat.living_space(v);
    comforts = new Comforts(v, landed, crew_count > 1, connection.linked);

    // data about greenhouses
    greenhouses = Greenhouse.Greenhouses(v);

    // other stuff
    gravioli = Sim.Graviolis(v);
  }
예제 #10
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));
        }