Esempio n. 1
0
        private void CloseFileIfOpen()
        {
            using (PooledDebugLogger logger = PooledDebugLogger.New(this))
            {
                logger.AppendFormat("Cleaning up file {0}...", this.fileName);

                if (this.csvBytes != null && this.csvBytes.Count > 0)
                {
                    logger.Append(" Writing remaining data...");
                    this.AsyncWriteData();
                }

                logger.Append(" Waiting for writes to finish.");
                while (this.outstandingWrites > 0)
                {
                    logger.Append('.');
                    System.Threading.Thread.Sleep(10);
                }

                if (this._outputFile != null)
                {
                    this._outputFile.Close();
                    this._outputFile = null;
                    logger.Append(" File closed.");
                }

                logger.Print(false);
            }
        }
Esempio n. 2
0
        public void OnDestroy()
        {
            using (PooledDebugLogger logger = PooledDebugLogger.New(this))
            {
                logger.Append("Destroying...");

                this.CloseFileIfOpen();

                logger.Append(" Done.");
                logger.Print(false);
            }
        }
Esempio n. 3
0
        protected void LoadModulesOfType <U>()
        {
            using (PooledDebugLogger sb = PooledDebugLogger.New(this))
            {
                sb.AppendLine("Loading modules...");

                AssemblyLoader.LoadedAssembly assy;
                for (int aIdx = 0; aIdx < AssemblyLoader.loadedAssemblies.Count; aIdx++)
                {
                    assy = AssemblyLoader.loadedAssemblies[aIdx];

                    Type[] loadedTypes = assy.assembly.GetExportedTypes();
                    Type   loadedType;
                    for (int tIdx = 0; tIdx < loadedTypes.Length; tIdx++)
                    {
                        loadedType = loadedTypes[tIdx];

                        if (
                            loadedType.IsInterface ||
                            loadedType.IsAbstract ||
                            !typeof(U).IsAssignableFrom(loadedType) ||
                            typeof(VOIDCore).IsAssignableFrom(loadedType))
                        {
                            continue;
                        }

                        sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name);

                        try
                        {
                            this.LoadModule(loadedType);
                            sb.AppendLine("Success.");
                        }
                        catch (Exception ex)
                        {
                            sb.AppendFormat("Failed, caught {0}\n", ex.GetType().Name);

                                                        #if DEBUG
                            Debug.LogException(ex);
                                                        #endif
                        }
                    }
                }

                this.LoadConfig();

                this.modulesLoaded = true;

                sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count);

                sb.Print();
            }
        }
        private void Awake()
        {
            this.lockID = "ARConnectionRequired";

            this.log = PooledDebugLogger.New(this);

            this.updateTimer = new System.Diagnostics.Stopwatch();

            this.toolbarTextures = new Dictionary <ConnectionStatus, string>();

            this.toolbarTextures[ConnectionStatus.None]       = "AntennaRange/Textures/toolbarIconNoConnection";
            this.toolbarTextures[ConnectionStatus.Suboptimal] = "AntennaRange/Textures/toolbarIconSubOptimal";
            this.toolbarTextures[ConnectionStatus.Optimal]    = "AntennaRange/Textures/toolbarIcon";

            this.appLauncherTextures = new Dictionary <ConnectionStatus, Texture>();

            this.appLauncherTextures[ConnectionStatus.None] =
                GameDatabase.Instance.GetTexture("AntennaRange/Textures/appLauncherIconNoConnection", false);
            this.appLauncherTextures[ConnectionStatus.Suboptimal] =
                GameDatabase.Instance.GetTexture("AntennaRange/Textures/appLauncherIconSubOptimal", false);
            this.appLauncherTextures[ConnectionStatus.Optimal] =
                GameDatabase.Instance.GetTexture("AntennaRange/Textures/appLauncherIcon", false);

            if (ToolbarManager.ToolbarAvailable && ARConfiguration.UseToolbarIfAvailable)
            {
                this.toolbarButton = ToolbarManager.Instance.add("AntennaRange", "ARConnectionStatus");

                this.toolbarButton.TexturePath = this.toolbarTextures[ConnectionStatus.None];
                this.toolbarButton.Text        = "AntennaRange";
                this.toolbarButton.Visibility  = new GameScenesVisibility(GameScenes.FLIGHT);
                this.toolbarButton.OnClick    += (e) => { this.buttonToggle(); };
            }

            GameEvents.onGameSceneLoadRequested.Add(this.onSceneChangeRequested);
            GameEvents.onVesselChange.Add(this.onVesselChange);

            usefulRelays = new List <IAntennaRelay>();
            UsefulRelays = usefulRelays.AsReadOnly();
        }
        public override void OnAwake()
        {
            base.OnAwake();

            GameEvents.onGameSceneLoadRequested.Add(this.GameSceneLoadHandler);
            GameEvents.OnPartPurchased.Add(this.PartPurchasedHandler);

            if (this.part.tryGetFirstModuleOfType <ModuleSAS>(out this.sasModule))
            {
                this.SASServiceLevel = this.sasModule.SASServiceLevel;
            }

            if (researchedPartsLoaded)
            {
                this.SASServiceLevel = maxSASServiceLevel;
                return;
            }

            if (HighLogic.CurrentGame == null || PartLoader.LoadedPartsList == null)
            {
                return;
            }

            switch (HighLogic.CurrentGame.Mode)
            {
            case Game.Modes.CAREER:
                this.Fields["SASServiceLevel"].guiActiveEditor = true;
                break;

            default:
                this.Fields["SASServiceLevel"].guiActiveEditor = false;

                Array apModes = Enum.GetValues(typeof(AutopilotSkill.Skills));
                int   autopilotMode;
                for (int idx = 0; idx < apModes.Length; idx++)
                {
                    try
                    {
                        autopilotMode = (int)apModes.GetValue(idx);

                        maxSASServiceLevel = Math.Max(maxSASServiceLevel, autopilotMode);
                    }
                    catch
                    {
                        this.LogDebug(
                            "Failed converting {0}.{1} to int.",
                            typeof(AutopilotSkill.Skills).GetType().Name,
                            Enum.GetName(typeof(AutopilotSkill.Skills), apModes.GetValue(idx))
                            );
                    }
                }

                researchedPartsLoaded = true;

                this.LogDebug("Sandbox mode: maxSASServiceLevel = {0}", maxSASServiceLevel);

                return;
            }

            this.LogDebug("Searching for researched parts with SAS modules...");

            using (var logger = PooledDebugLogger.New(this))
            {
                AvailablePart part;
                for (int idx = 0; idx < PartLoader.LoadedPartsList.Count; idx++)
                {
                    part = PartLoader.LoadedPartsList[idx];

                    logger.AppendFormat("Checking {0}...", part.title);

                    if (ResearchAndDevelopment.PartTechAvailable(part))
                    {
                        logger.Append(" researched...");

                        ModuleSAS sasModule;

                        if (part.partPrefab.tryGetFirstModuleOfType(out sasModule))
                        {
                            logger.Append(" has SAS module, adding to list.");

                            researchedSASParts.Add(part);

                            maxSASServiceLevel = Math.Max(sasModule.SASServiceLevel, maxSASServiceLevel);

                            logger.AppendFormat(" \n\tmaxSASServiceLevel = {0}.", maxSASServiceLevel);
                        }
                    }
                                        #if DEBUG
                    else
                    {
                        logger.Append(" not researched!");
                    }
                                        #endif

                    logger.Append('\n');
                }

                logger.Append("Researched SAS parts loaded.");

                logger.Print();
            }

            researchedPartsLoaded = true;
        }
Esempio n. 6
0
        public void FixedUpdate()
        {
            if (
                HighLogic.LoadedSceneIsFlight &&
                FlightGlobals.Vessels != null &&
                this.vessel != null &&
                this.dockingModule != null
                )
            {
                                #if DEBUG
                bool foundApproach = false;
                                #endif

                PooledDebugLogger verboseLog = PooledDebugLogger.New(this);

                                #if DEBUG
                try
                {
                                #endif

                verboseLog.AppendFormat(" ({0}_{1}) on {2}",
                                        this.part.partInfo.name, this.part.craftID, this.vessel.vesselName);
                verboseLog.AppendFormat("\nChecking within acquireRangeSqr: {0}", this.acquireRangeSqr);

                verboseLog.AppendFormat("this.dockingModule: {0}\n", this.dockingModule == null ?
                                        "null" : this.dockingModule.ToString());

                verboseLog.AppendFormat("this.dockingModule.state: {0}\n",
                                        this.dockingModule == null || this.dockingModule.state == null ?
                                        "null" :this.dockingModule.state.ToString());

                // If we're already docked or pre-attached...
                if (this.dockingModule.state == "Docked" || this.dockingModule.state == "PreAttached")
                {
                    // ...and if the timeout timer is running...
                    if (this.timeoutTimer.IsRunning)
                    {
                        // ...reset the timeout timer
                        this.timeoutTimer.Reset();
                    }

                    // ...skip this check
                    return;
                }

                // If the timeout timer is running, we found a match recently.  If we haven't found a match in more than
                // five seconds, it's not recent anymore, so reset our size to default.
                if (this.timeoutTimer.IsRunning && this.timeoutTimer.ElapsedMilliseconds > 5000)
                {
                    verboseLog.AppendFormat("\nNo target detected within 5 seconds, timing out.");

                    if (this.dockingModule.state != "Docked")
                    {
                        verboseLog.AppendFormat("\nReverting to default nodeType: {0}", this.defaultSize);
                        this.currentSize = this.defaultSize;
                    }

                    this.timeoutTimer.Reset();
                }

                bool foundTargetNode     = false;
                float closestNodeDistSqr = this.acquireRangeSqr * 4f;

                verboseLog.Append("Starting Vessels loop.");

                // Check all vessels for potential docking targets
                Vessel vessel;
                for (int vIdx = 0; vIdx < FlightGlobals.Vessels.Count; vIdx++)
                {
                    vessel = FlightGlobals.Vessels[vIdx];
                    if (vessel == null)
                    {
                        verboseLog.Append("Skipping null vessel.");
                        continue;
                    }

                    // Skip vessels that are just way too far away.
                    if (this.vessel.sqrDistanceTo(vessel) > this.vesselFilterDistanceSqr)
                    {
                        verboseLog.AppendFormat("\nSkipping distant vessel {0} (sqrDistance {1})",
                                                vessel.vesselName,
                                                (vessel.GetWorldPos3D() - this.dockingModule.nodeTransform.position).sqrMagnitude
                                                );
                        continue;
                    }

                    verboseLog.AppendFormat("\nChecking nearby vessel {0} (sqrDistance {1})",
                                            vessel.vesselName,
                                            (vessel.GetWorldPos3D() - this.dockingModule.nodeTransform.position).sqrMagnitude
                                            );

                    // Since this vessel is not too far away, check all docking nodes on the vessel.
                    IList <ModuleDockingNode> potentialNodes = vessel.getModulesOfType <ModuleDockingNode>();
                    ModuleDockingNode         potentialTargetNode;
                    for (int nIdx = 0; nIdx < potentialNodes.Count; nIdx++)
                    {
                        potentialTargetNode = potentialNodes[nIdx];

                        if (potentialTargetNode == null)
                        {
                            verboseLog.AppendFormat("\nSkipping potentialTargetNode at index {0} because it is null",
                                                    nIdx);
                            continue;
                        }

                        if (potentialTargetNode.part == null)
                        {
                            verboseLog.AppendFormat("\nSkipping potentialTargetNode at index {0} because its part is null",
                                                    nIdx);
                            continue;
                        }

                        if (potentialTargetNode.nodeTransform == null)
                        {
                            verboseLog.AppendFormat("\nSkipping potentialTargetNode at index {0} because its node transform is null",
                                                    nIdx);
                            continue;
                        }

                        verboseLog.AppendFormat("\nFound potentialTargetNode: {0}", potentialTargetNode);
                        verboseLog.AppendFormat("\n\tpotentialTargetNode.state: {0}", potentialTargetNode.state);
                        verboseLog.AppendFormat("\n\tpotentialTargetNode.nodeType: {0}", potentialTargetNode.nodeType);

                        // We can't skip the current vessel, because it's possible to dock parts on a single vessel to
                        // each other.  Still, we can't dock a port to itself, so skip this part.
                        if (potentialTargetNode.part == this.part)
                        {
                            verboseLog.AppendFormat("\nDiscarding potentialTargetNode: on this part.");
                            continue;
                        }

                        // If this docking node is already docked, we can't dock to it, so skip it.
                        if (
                            potentialTargetNode.state.Contains("Docked") ||
                            potentialTargetNode.state.Contains("PreAttached"))
                        {
                            verboseLog.Append("\nDiscarding potentialTargetNode: not ready.");
                            continue;
                        }

                        float thisNodeDistSqr =
                            (potentialTargetNode.nodeTransform.position - this.dockingModule.nodeTransform.position)
                            .sqrMagnitude;

                        verboseLog.AppendFormat(
                            "\n\tChecking potentialTargetNode sqrDistance against the lesser of acquireRangeSqr and " +
                            "closestNodeDistSqr ({0})",
                            Mathf.Min(this.acquireRangeSqr * 4f, closestNodeDistSqr)
                            );

                        // Only bother checking nodes closer than twice our acquire range.  We have to check before we
                        // get within acquire range to make sure Squad's code will catch us when we get there.
                        if (thisNodeDistSqr <= Mathf.Min(this.acquireRangeSqr * 4f, closestNodeDistSqr))
                        {
                                                        #if DEBUG
                            foundApproach = true;
                                                        #endif

                            verboseLog.AppendFormat(
                                "\n\tpotentialTargetNode is nearby ({0}), checking if adaptive.", thisNodeDistSqr);

                            ModuleAdaptiveDockingNode targetAdaptiveNode = null;

                            string targetSize;
                            targetSize = string.Empty;

                            // adapt to non-adaptive docking nodes
                            if (this.validSizes.Contains(potentialTargetNode.nodeType))
                            {
                                targetSize       = potentialTargetNode.nodeType;
                                this.currentSize = targetSize;
                            }
                            // Otherwise, look for another adaptive node.
                            else
                            {
                                // Check the part for an AdaptiveDockingNode
                                targetAdaptiveNode = potentialTargetNode.part
                                                     .getFirstModuleOfType <ModuleAdaptiveDockingNode>();
                            }

                            // If we've found an AdaptiveDockingNode...
                            if (targetAdaptiveNode != null)
                            {
                                verboseLog.AppendFormat("\n\tpotentialTargetNode is adaptive.");
                                verboseLog.AppendFormat("\n\tdefaultSize: {0}", targetAdaptiveNode.defaultSize);
                                verboseLog.AppendFormat("\n\tvalidSizes: {0}", targetAdaptiveNode.validSizes);

                                // ...and if we can become its largest (default) size...
                                // to their default size.
                                if (this.validSizes.Contains(targetAdaptiveNode.defaultSize))
                                {
                                    // ...target its default size.
                                    targetSize = targetAdaptiveNode.defaultSize;
                                }
                                // ...otherwise, look for a common size.
                                else
                                {
                                    string commonNodeType = GetGreatestCommonNodeType(this, targetAdaptiveNode);

                                    // ...if we didn't find a common size, stop processing this node
                                    if (commonNodeType == string.Empty)
                                    {
                                        verboseLog.AppendFormat("\n\tInvalid adaptive target: no common node types.");
                                        continue;
                                    }

                                    targetSize = commonNodeType;
                                    targetAdaptiveNode.currentSize = targetSize;

                                    verboseLog.AppendFormat(
                                        "\n\tTarget nodeType set to commonNodeType: {0}", targetSize);
                                }
                            }
                                                        #if DEBUG
                            else
                            {
                                verboseLog.AppendFormat("\n\tpotentialTargetNode is not adaptive.");
                                verboseLog.AppendFormat("\n\tnodeType: {0}", potentialTargetNode.nodeType);
                            }
                                                        #endif

                            // If we never found a target size, it's not a match, so stop processing.
                            if (targetSize == string.Empty)
                            {
                                continue;
                            }

                            // ...otherwise, log this node as the closest and adapt to the target size.
                            closestNodeDistSqr = thisNodeDistSqr;
                            this.currentSize   = targetSize;
                            foundTargetNode    = true;


                            verboseLog.AppendFormat("\n\tLocal nodeType set to commonNodeType: {0}", targetSize);
                            verboseLog.AppendFormat("\n\tFound suitable docking node.");
                            verboseLog.AppendFormat("\n\ttargetSize: {0}", targetSize);

                            verboseLog.AppendFormat("\n\tForward vector dot product: {0} (acquire minimum: {1})",
                                                    Vector3.Dot(potentialTargetNode.nodeTransform.forward,
                                                                this.dockingModule.nodeTransform.forward),
                                                    this.dockingModule.acquireMinFwdDot
                                                    );

                            verboseLog.AppendFormat("\n\tUp vector dot product: {0} (acquire minimum: {1})",
                                                    Vector3.Dot(potentialTargetNode.nodeTransform.up, this.dockingModule.nodeTransform.up),
                                                    this.dockingModule.acquireMinRollDot
                                                    );
                        }
                        else
                        {
                            verboseLog.AppendFormat(
                                "\nDiscarding potentialTargetNode: too far away (thisNodeDistSqr: {0})",
                                thisNodeDistSqr
                                );
                        }
                    }

                    verboseLog.Append('\n');
                }

                verboseLog.Append("\nFixedUpdate Finished.");

                if (foundTargetNode)
                {
                    if (this.timeoutTimer.IsRunning)
                    {
                        this.timeoutTimer.Reset();
                    }

                    this.timeoutTimer.Start();
                }

                                #if DEBUG
            }
            finally
            {
                // if (foundApproach)
                verboseLog.Print();
            }
                                #endif
            }
        }
        /// <summary>
        /// Override ModuleDataTransmitter.TransmitData to check against CanTransmit and fail out when CanTransmit
        /// returns false.
        /// </summary>
        /// <param name="dataQueue">List of <see cref="ScienceData"/> to transmit.</param>
        public new void TransmitData(List <ScienceData> dataQueue)
        {
            this.LogDebug(
                "TransmitData(List<ScienceData> dataQueue, Callback callback) called.  dataQueue.Count={0}",
                dataQueue.Count
                );

            if (this.CanTransmit())
            {
                ScreenMessages.PostScreenMessage(this.buildTransmitMessage(), 4f, ScreenMessageStyle.UPPER_LEFT);

                this.LogDebug(
                    "CanTransmit in TransmitData, calling base.TransmitData with dataQueue=[{0}] and callback={1}",
                    dataQueue.SPrint()
                    );

                base.TransmitData(dataQueue);
            }
            else
            {
                this.LogDebug("{0} unable to transmit during TransmitData.", this.part.partInfo.title);

                var logger = PooledDebugLogger.New(this);

                IList <ModuleScienceContainer> vesselContainers = this.vessel.getModulesOfType <ModuleScienceContainer>();
                ModuleScienceContainer         scienceContainer;
                for (int cIdx = 0; cIdx < vesselContainers.Count; cIdx++)
                {
                    scienceContainer = vesselContainers[cIdx];

                    logger.AppendFormat("Checking ModuleScienceContainer in {0}\n",
                                        scienceContainer.part.partInfo.title);

                    if (
                        scienceContainer.capacity != 0 &&
                        scienceContainer.GetScienceCount() >= scienceContainer.capacity
                        )
                    {
                        logger.Append("\tInsufficient capacity, skipping.\n");
                        continue;
                    }

                    List <ScienceData> dataStored = new List <ScienceData>();

                    ScienceData data;
                    for (int dIdx = 0; dIdx < dataQueue.Count; dIdx++)
                    {
                        data = dataQueue[dIdx];
                        if (!scienceContainer.allowRepeatedSubjects && scienceContainer.HasData(data))
                        {
                            logger.Append("\tAlready contains subject and repeated subjects not allowed, skipping.\n");
                            continue;
                        }

                        logger.AppendFormat("\tAcceptable, adding data on subject {0}... ", data.subjectID);
                        if (scienceContainer.AddData(data))
                        {
                            logger.Append("done, removing from queue.\n");

                            dataStored.Add(data);
                        }
                                                #if DEBUG
                        else
                        {
                            logger.Append("failed.\n");
                        }
                                                #endif
                    }

                    dataQueue.RemoveAll(i => dataStored.Contains(i));

                    logger.AppendFormat("\t{0} data left in queue.", dataQueue.Count);
                }

                logger.Print();

                if (dataQueue.Count > 0)
                {
                    using (PooledStringBuilder sb = PooledStringBuilder.Get())
                    {
                        sb.Append('[');
                        sb.Append(this.part.partInfo.title);
                        sb.AppendFormat("]: {0} data items could not be saved: no space available in data containers.\n");
                        sb.Append("Data to be discarded:\n");

                        ScienceData data;
                        for (int dIdx = 0; dIdx < dataQueue.Count; dIdx++)
                        {
                            data = dataQueue[dIdx];
                            sb.AppendFormat("\t{0}\n", data.title);
                        }

                        ScreenMessages.PostScreenMessage(sb.ToString(), 4f, ScreenMessageStyle.UPPER_LEFT);

                        this.LogDebug(sb.ToString());
                    }
                }

                this.PostCannotTransmitError();
            }

            this.LogDebug(
                "distance: " + this.CurrentLinkSqrDistance
                + " packetSize: " + this.packetSize
                + " packetResourceCost: " + this.packetResourceCost
                );
        }
Esempio n. 8
0
        /// <summary>
        /// Finds the nearest relay.
        /// </summary>
        /// <returns>The nearest relay or null, if no relays in range.</returns>
        public void FindNearestRelay()
        {
            if (!FlightGlobals.ready)
            {
                return;
            }

            PooledDebugLogger log;

                        #if DEBUG
            log = PooledDebugLogger.New(this);
                        #endif

                        #if BENCH
            this.performanceTimer.Restart();

            long startVesselLoopTicks;
            long totalVesselLoopTicks;

            string slowestLOSVesselName  = string.Empty;
            long   slowestLOSVesselTicks = long.MinValue;
            long   startLOSVesselTicks;
            long   totalLOSVesselTicks;

            string slowestCircularVesselName  = string.Empty;
            long   slowestCircularVesselTicks = long.MinValue;
            long   startCircularVesselTicks;
            long   totalCircularVesselTicks;

            long startKerbinLOSTicks;
            long totalKerbinLOSTicks;
            long statusResolutionTicks;

            ushort usefulVesselCount = 0;
                        #endif

            log.AppendFormat("{0}: Target search started).", this.ToString());

                        #if DEBUG
            try {
                        #endif

            // Declare a bunch of variables we'll be using.
            CelestialBody bodyOccludingBestOccludedRelay = null;
            IAntennaRelay needle;

            RelayDataCost cheapestRelayRate         = RelayDataCost.Infinity;
            RelayDataCost cheapestOccludedRelayRate = RelayDataCost.Infinity;

            RelayDataCost potentialRelayRate;

            RelayDataCost kerbinRelayRate = this.GetPotentialLinkCost(Kerbin);

            bool isCircular;
            int iterCount;

            // Blank everything we're trying to find before the search.
            this.firstOccludingBody = null;
            this.bestOccludedRelay  = null;
            this.targetRelay        = null;
            this.nearestRelay       = null;

            // Default to KerbinDirect = true in case something in here doesn't work right.
            this.KerbinDirect = true;

            /*
             * Loop through the useful relays as determined by ARFlightController and check each for line of sight and
             * distance, searching for the relay with the best distance/maxRange ratio that is in sight, in range, and
             * can transmit, also stashing the "best" relay outside of line of sight for failure report.
             * */
            IAntennaRelay potentialBestRelay;
            CelestialBody fob;

                        #if BENCH
            startVesselLoopTicks = performanceTimer.ElapsedTicks;
                        #endif

            for (int rIdx = 0; rIdx < ARFlightController.UsefulRelays.Count; rIdx++)
            {
                potentialBestRelay = ARFlightController.UsefulRelays[rIdx];
                log.AppendFormat("\n\tgot useful relay {0}",
                                 potentialBestRelay == null ? "null" : potentialBestRelay.ToString());

                if (potentialBestRelay == null)
                {
                    log.Append("\n\t...skipping null relay");
                    continue;
                }

                if (potentialBestRelay == this || potentialBestRelay.vessel == this.vessel)
                {
                    log.AppendFormat(
                        "\n\t...skipping relay {0} because it or its vessel ({1}) is the same as ours" +
                        "\n\t\t(our vessel is {2})",
                        potentialBestRelay,
                        potentialBestRelay.vessel == null ? "null" : potentialBestRelay.vessel.vesselName,
                        this.vessel == null ? "null" : this.vessel.vesselName
                        );
                    continue;
                }

                                #if BENCH
                usefulVesselCount++;
                                #endif

                // Find the distance from here to the vessel...
                log.Append("\n\tgetting cost to potential vessel");
                potentialRelayRate = potentialBestRelay.CurrentNetworkLinkCost +
                                     this.GetPotentialLinkCost(potentialBestRelay);

                log.AppendFormat(
                    "\n\tpotentialRelayRate = {0} ({1} + {2})",
                    potentialRelayRate,
                    potentialBestRelay.CurrentNetworkLinkCost,
                    this.GetPotentialLinkCost(potentialBestRelay)
                    );

                                #if BENCH
                startLOSVesselTicks = performanceTimer.ElapsedTicks;
                                #endif

                log.Append("\n\t\tdoing LOS check");
                // Skip vessels to which we do not have line of sight.
                if (
                    ARConfiguration.RequireLineOfSight &&
                    !this.vessel.hasLineOfSightTo(potentialBestRelay.vessel, out fob, ARConfiguration.RadiusRatio)
                    )
                {
                                        #if BENCH
                    totalLOSVesselTicks = performanceTimer.ElapsedTicks - startLOSVesselTicks;

                    if (totalLOSVesselTicks > slowestLOSVesselTicks)
                    {
                        slowestLOSVesselTicks = totalLOSVesselTicks;
                        slowestLOSVesselName  = vessel.vesselName;
                    }
                                        #endif

                    log.Append("\n\t\t...failed LOS check");

                    log.AppendFormat("\n\t\t\t{0}: Relay {1} not in line of sight.",
                                     this.ToString(), potentialBestRelay);

                    log.AppendFormat("\n\t\t\tpotentialRelayRate: {0}", potentialRelayRate);
                    log.AppendFormat("\n\t\t\tcheapestOccludedRelayRate: {0}", cheapestOccludedRelayRate);

                    if (
                        (potentialRelayRate < cheapestRelayRate) &&
                        this.IsInRangeOf(potentialBestRelay) &&
                        potentialBestRelay.CanTransmit()
                        )
                    {
                        log.Append("\n\t\t...vessel is cheapest and in range and potentialBestRelay can transmit");
                        log.AppendFormat("\n\t\t...{0} found new best occluded relay {1}", this, potentialBestRelay);

                        this.bestOccludedRelay         = potentialBestRelay;
                        bodyOccludingBestOccludedRelay = fob;
                        cheapestOccludedRelayRate      = potentialRelayRate;
                    }
                    else
                    {
                        log.Append("\n\t\t...vessel is not close enough to check for occluded relays, carrying on");
                    }

                    continue;
                }
                                #if BENCH
                else
                {
                    totalLOSVesselTicks = performanceTimer.ElapsedTicks - startLOSVesselTicks;
                }

                if (totalLOSVesselTicks > slowestLOSVesselTicks)
                {
                    slowestLOSVesselTicks = totalLOSVesselTicks;
                    slowestLOSVesselName  = vessel.vesselName;
                }
                                #endif

                log.Append("\n\t\t...passed LOS check");

                /*
                 * ...so that we can skip the vessel if it is further away than a vessel we've already checked.
                 * */
                if (potentialRelayRate > cheapestRelayRate)
                {
                    log.AppendFormat(
                        "\n\t{0}: Relay {1} discarded because it is more expensive than the cheapest relay." +
                        "\n\t\t({2}, {3} > {4})",
                        this.ToString(),
                        potentialBestRelay,
                        this.nearestRelay == null ? "NULL" : this.nearestRelay.ToString(),
                        potentialRelayRate, cheapestRelayRate
                        );
                    continue;
                }

                log.Append("\n\t\t...passed distance check");

                if (potentialBestRelay.CanTransmit())
                {
                                        #if BENCH
                    startCircularVesselTicks = performanceTimer.ElapsedTicks;
                                        #endif

                    needle     = potentialBestRelay;
                    isCircular = false;

                    iterCount = 0;
                    while (needle != null)
                    {
                        iterCount++;

                        if (needle.KerbinDirect)
                        {
                            break;
                        }

                        if (needle.targetRelay == null)
                        {
                            break;
                        }

                        if (needle.targetRelay.vessel == this.vessel || needle == this.moduleRef)
                        {
                            isCircular = true;
                            break;
                        }

                        // Avoid infinite loops when we're not catching things right.
                        if (iterCount > FlightGlobals.Vessels.Count)
                        {
                            this.LogError(
                                "iterCount exceeded while checking for circular network; assuming it is circular" +
                                "\n\tneedle={0}" +
                                "\n\tthis.moduleRef={1}",
                                needle == null ? "null" : string.Format(
                                    "{0}, needle.KerbinDirect={1}, needle.targetRelay={2}",
                                    needle, needle.KerbinDirect, needle.targetRelay == null ? "null" : string.Format(
                                        "{0}\n\tneedle.targetRelay.vessel={1}",
                                        needle.targetRelay,
                                        needle.targetRelay.vessel == null ?
                                        "null" : needle.targetRelay.vessel.vesselName
                                        )
                                    ),
                                this.moduleRef == null ? "null" : this.moduleRef.ToString()
                                );
                            isCircular = true;
                            break;
                        }

                        needle = needle.targetRelay;
                    }

                    if (!isCircular)
                    {
                        cheapestRelayRate = potentialRelayRate;
                        this.nearestRelay = potentialBestRelay;

                        log.AppendFormat("\n\t{0}: found new cheapest relay {1} ({2} EC/MiT)",
                                         this.ToString(),
                                         this.nearestRelay.ToString(),
                                         cheapestRelayRate
                                         );
                    }
                    else
                    {
                        log.AppendFormat("\n\t\t...connection to {0} would result in a circular network, skipping",
                                         potentialBestRelay
                                         );
                    }

                                        #if BENCH
                    totalCircularVesselTicks = performanceTimer.ElapsedTicks - startCircularVesselTicks;

                    if (totalCircularVesselTicks > slowestCircularVesselTicks)
                    {
                        slowestCircularVesselName  = vessel.vesselName;
                        slowestCircularVesselTicks = totalCircularVesselTicks;
                    }
                                        #endif
                }
            }

                        #if BENCH
            totalVesselLoopTicks = performanceTimer.ElapsedTicks - startVesselLoopTicks;
                        #endif

            CelestialBody bodyOccludingKerbin = null;

            log.AppendFormat("\n{0} ({1}): Search done, figuring status.", this.ToString(), this.GetType().Name);
            log.AppendFormat(
                "\n{0}: nearestRelay={1} ({2})), bestOccludedRelay={3} ({4}), kerbinRelayRate={5} EC/MiT)",
                this,
                this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
                cheapestRelayRate,
                this.bestOccludedRelay == null ? "null" : this.bestOccludedRelay.ToString(),
                cheapestOccludedRelayRate,
                kerbinRelayRate
                );

                        #if BENCH
            startKerbinLOSTicks = this.performanceTimer.ElapsedTicks;
                        #endif

            // If we don't have LOS to Kerbin, focus on relays
            if (
                ARConfiguration.RequireLineOfSight &&
                !this.vessel.hasLineOfSightTo(Kerbin, out bodyOccludingKerbin, ARConfiguration.RadiusRatio)
                )
            {
                                #if BENCH
                totalKerbinLOSTicks = this.performanceTimer.ElapsedTicks - startKerbinLOSTicks;
                                #endif
                log.AppendFormat("\n\tKerbin LOS is blocked by {0}.", bodyOccludingKerbin.bodyName);

                // If we're in range of the "nearest" (actually cheapest) relay, use it.
                if (this.IsInRangeOf(this.nearestRelay))
                {
                    log.AppendFormat("\n\t\tCan transmit to nearby relay {0}).",
                                     this.nearestRelay == null ? "null" : this.nearestRelay.ToString()
                                     );

                    this.KerbinDirect = false;
                    this.canTransmit  = true;
                    this.targetRelay  = this.nearestRelay;
                }
                // If this isn't true, we can't transmit, but pick a second best of bestOccludedRelay and Kerbin anyway
                else
                {
                    log.AppendFormat("\n\t\tCan't transmit to nearby relay {0}.",
                                     this.nearestRelay == null ? "null" : this.nearestRelay.ToString()
                                     );

                    this.canTransmit = false;

                    // If the best occluded relay is cheaper than Kerbin, check it against the nearest relay.
                    // Since cheapestOccludedRelayRate is infinity if there are no occluded relays, this is safe
                    if (cheapestOccludedRelayRate < kerbinRelayRate)
                    {
                        log.AppendFormat("\n\t\t\tBest occluded relay is cheaper than Kerbin ({0} < {1})",
                                         cheapestOccludedRelayRate, kerbinRelayRate);

                        this.KerbinDirect = false;

                        // If the nearest relay is cheaper than the best occluded relay, pick it.
                        // Since cheapestRelayRate is infinity if there are no nearby relays, this is safe.
                        if (cheapestRelayRate < cheapestOccludedRelayRate)
                        {
                            log.AppendFormat("\n\t\t\t\t...but the cheapest relay is cheaper ({0} < {1}), so picking it.",
                                             cheapestRelayRate, cheapestOccludedRelayRate);

                            this.targetRelay        = this.nearestRelay;
                            this.firstOccludingBody = null;
                        }
                        // Otherwise, target the best occluded relay.
                        else
                        {
                            log.AppendFormat("\n\t\t\t\t...and cheaper than the nearest relay ({0} >= {1}), so picking it.",
                                             cheapestRelayRate, cheapestOccludedRelayRate);

                            this.targetRelay        = bestOccludedRelay;
                            this.firstOccludingBody = bodyOccludingBestOccludedRelay;
                        }
                    }
                    // Otherwise, check Kerbin against the "nearest" (cheapest) relay.
                    else
                    {
                        log.AppendFormat("\n\t\t\tKerbin is cheaper than the best occluded relay ({0} >= {1})",
                                         cheapestOccludedRelayRate, kerbinRelayRate);

                        // If the "nearest" (cheapest) relay is cheaper than Kerbin, pick it.
                        // Since cheapestRelayRate is infinity if there are no nearby relays, this is safe.
                        if (cheapestRelayRate < kerbinRelayRate)
                        {
                            log.AppendFormat("\n\t\t\t\t...but the nearest relay is cheaper ({0} < {1}), so picking it.",
                                             cheapestRelayRate, kerbinRelayRate);

                            // Since we have LOS, blank the first occluding body.
                            this.firstOccludingBody = null;

                            this.KerbinDirect = false;
                            this.targetRelay  = this.nearestRelay;
                        }
                        // Otherwise, pick Kerbin.
                        else
                        {
                            log.AppendFormat("\n\t\t\t\t...and cheaper than the nearest relay ({0} >= {1}), so picking it.",
                                             cheapestRelayRate, kerbinRelayRate);

                            this.KerbinDirect       = true;
                            this.firstOccludingBody = bodyOccludingKerbin;
                            this.targetRelay        = null;
                        }
                    }
                }
            }
            // If we do have LOS to Kerbin, try to prefer the closest of nearestRelay and Kerbin
            else
            {
                                #if BENCH
                totalKerbinLOSTicks = this.performanceTimer.ElapsedTicks - startKerbinLOSTicks;
                                #endif

                log.AppendFormat("\n\tKerbin is in LOS.");

                // If the nearest relay is in range, we can transmit.
                if (this.IsInRangeOf(this.nearestRelay))
                {
                    log.AppendFormat("\n\t\tCan transmit to nearby relay {0} (in range).",
                                     this.nearestRelay == null ? "null" : this.nearestRelay.ToString()
                                     );

                    this.canTransmit = true;

                    // If the nearestRelay is closer than Kerbin, use it.
                    if (cheapestRelayRate < kerbinRelayRate)
                    {
                        log.AppendFormat("\n\t\t\tPicking relay {0} over Kerbin ({1} < {2}).",
                                         this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
                                         cheapestRelayRate, kerbinRelayRate);

                        this.KerbinDirect = false;
                        this.targetRelay  = this.nearestRelay;
                    }
                    // Otherwise, Kerbin is closer, so use it.
                    else
                    {
                        log.AppendFormat("\n\t\t\tBut picking Kerbin over nearby relay {0} ({1} >= {2}).",
                                         this.nearestRelay == null ? "null" : this.nearestRelay.ToString(),
                                         cheapestRelayRate, kerbinRelayRate);

                        this.KerbinDirect = true;
                        this.targetRelay  = null;
                    }
                }
                // If the nearest relay is out of range, we still need to check on Kerbin.
                else
                {
                    log.AppendFormat("\n\t\tCheapest relay {0} is out of range.",
                                     this.nearestRelay == null ? "null" : this.nearestRelay.ToString()
                                     );

                    // If Kerbin is in range, use it.
                    if (this.IsInRangeOf(Kerbin))
                    {
                        log.AppendFormat("\n\t\t\tCan transmit to Kerbin (in range).");

                        this.canTransmit  = true;
                        this.KerbinDirect = true;
                        this.targetRelay  = null;
                    }
                    // If Kerbin is out of range and the nearest relay is out of range, pick a second best between
                    // Kerbin and bestOccludedRelay
                    else
                    {
                        log.AppendFormat("\n\t\t\tCan't transmit to Kerbin (out of range).");

                        this.canTransmit = false;

                        // If the best occluded relay is cheaper than Kerbin, check it against the nearest relay.
                        // Since bestOccludedSqrDistance is infinity if there are no occluded relays, this is safe
                        if (cheapestOccludedRelayRate < kerbinRelayRate)
                        {
                            log.AppendFormat("\n\t\t\tBest occluded relay is closer than Kerbin ({0} < {1})",
                                             cheapestOccludedRelayRate, kerbinRelayRate);

                            this.KerbinDirect = false;

                            // If the nearest relay is closer than the best occluded relay, pick it.
                            // Since cheapestRelayRate is infinity if there are no nearby relays, this is safe.
                            if (cheapestRelayRate < cheapestOccludedRelayRate)
                            {
                                log.AppendFormat("\n\t\t\t\t...but the cheapest relay is cheaper ({0} < {1}), so picking it.",
                                                 cheapestRelayRate, cheapestOccludedRelayRate);

                                this.targetRelay        = this.nearestRelay;
                                this.firstOccludingBody = null;
                            }
                            // Otherwise, target the best occluded relay.
                            else
                            {
                                log.AppendFormat("\n\t\t\t\t...and cheaper than the cheapest relay ({0} >= {1}), so picking it.",
                                                 cheapestRelayRate, cheapestOccludedRelayRate);

                                this.targetRelay        = bestOccludedRelay;
                                this.firstOccludingBody = bodyOccludingBestOccludedRelay;
                            }
                        }
                        // Otherwise, check Kerbin against the nearest relay.
                        // Since we have LOS, blank the first occluding body.
                        else
                        {
                            log.AppendFormat("\n\t\t\tKerbin is cheaper than the best occluded relay ({0} >= {1})",
                                             cheapestOccludedRelayRate, kerbinRelayRate);

                            this.firstOccludingBody = null;

                            // If the nearest relay is cheaper than Kerbin, pick it.
                            // Since cheapestRelayRate is infinity if there are no nearby relays, this is safe.
                            if (cheapestRelayRate < kerbinRelayRate)
                            {
                                log.AppendFormat("\n\t\t\t\t...but the nearest relay is cheaper ({0} < {1}), so picking it.",
                                                 cheapestRelayRate, kerbinRelayRate);

                                this.KerbinDirect = false;
                                this.targetRelay  = this.nearestRelay;
                            }
                            // Otherwise, pick Kerbin.
                            else
                            {
                                log.AppendFormat("\n\t\t\t\t...and cheaper than the nearest relay ({0} >= {1}), so picking it.",
                                                 cheapestRelayRate, kerbinRelayRate);

                                this.KerbinDirect = true;
                                this.targetRelay  = null;
                            }
                        }
                    }
                }
            }

            if (ARConfiguration.UseAdditiveRanges)
            {
                if (this.KerbinDirect)
                {
                    this.NominalLinkSqrDistance = this.nominalTransmitDistance * ARConfiguration.KerbinNominalRange;
                    this.MaximumLinkSqrDistance = this.maxTransmitDistance * ARConfiguration.KerbinRelayRange;
                }
                else
                {
                    this.NominalLinkSqrDistance = this.nominalTransmitDistance * this.targetRelay.nominalTransmitDistance;
                    this.MaximumLinkSqrDistance = this.maxTransmitDistance * this.targetRelay.maxTransmitDistance;
                }
            }
            else
            {
                this.NominalLinkSqrDistance = this.nominalTransmitDistance * this.nominalTransmitDistance;
                this.MaximumLinkSqrDistance = this.maxTransmitDistance * this.maxTransmitDistance;
            }

            if (this.canTransmit)
            {
                if (this.CurrentLinkSqrDistance < this.NominalLinkSqrDistance)
                {
                    this.LinkStatus = ConnectionStatus.Optimal;
                }
                else
                {
                    this.LinkStatus = ConnectionStatus.Suboptimal;
                }
            }
            else
            {
                this.LinkStatus = ConnectionStatus.None;
            }

                        #if BENCH
            statusResolutionTicks = performanceTimer.ElapsedTicks - startKerbinLOSTicks - totalKerbinLOSTicks;
                        #endif

            log.AppendFormat("\n{0}: Target search and status determination complete.", this.ToString());

                        #if DEBUG
        }

        catch (Exception ex) {
            log.AppendFormat("\nCaught {0}: {1}\n{2}", ex.GetType().FullName, ex.ToString(), ex.StackTrace);
                        #if QUIT_ON_EXCEPTION
            UnityEngine.Application.Quit();
                        #endif
        } finally {
                        #endif
            log.Print(false);
                        #if DEBUG
        }
                        #endif

                        #if BENCH
            AntennaRelay.searchTimer += (ulong)this.performanceTimer.ElapsedTicks;
            AntennaRelay.searchCount++;
            this.performanceTimer.Stop();

            double averageSearchTime = (double)AntennaRelay.searchTimer / (double)AntennaRelay.searchCount;

            if (AntennaRelay.searchCount >= 8000u / (ulong)ARConfiguration.UpdateDelay)
            {
                AntennaRelay.searchCount = 0u;
                AntennaRelay.searchTimer = 0u;

                AntennaRelay.averager.AddItem(averageSearchTime);
                AntennaRelay.doubleAverageTime = (long)(AntennaRelay.averager.Average * 2d);
            }

            if (this.performanceTimer.ElapsedTicks > AntennaRelay.doubleAverageTime)
            {
                System.Text.StringBuilder sb = Tools.GetStringBuilder();

                sb.AppendFormat(Tools.SIFormatter, "[AntennaRelay] FindNearestRelay search for {0}" +
                                " took significantly longer than average ({1:S3}s vs {2:S3}s)",
                                this.ToString(),
                                (double)this.performanceTimer.ElapsedTicks / (double)System.Diagnostics.Stopwatch.Frequency,
                                (double)AntennaRelay.averager.Average / (double)System.Diagnostics.Stopwatch.Frequency
                                );

                sb.AppendFormat(Tools.SIFormatter, "\n\tVessel loop time: {0:S3}s",
                                (double)totalVesselLoopTicks / (double)System.Diagnostics.Stopwatch.Frequency
                                );

                sb.AppendFormat(Tools.SIFormatter, "\n\t\tAverage vessel time for each of {1} vessels: {0:S3}s",
                                (double)totalVesselLoopTicks / (double)System.Diagnostics.Stopwatch.Frequency /
                                (double)usefulVesselCount,
                                usefulVesselCount
                                );

                sb.AppendFormat(Tools.SIFormatter, "\n\t\tSlowest vessel LOS check: {0:S3}s to {1}",
                                (double)slowestLOSVesselTicks / (double)System.Diagnostics.Stopwatch.Frequency,
                                slowestLOSVesselName
                                );

                sb.AppendFormat(Tools.SIFormatter, "\n\t\tSlowest circular relay check: {0:S3}s for {1}",
                                (double)slowestCircularVesselTicks / (double)System.Diagnostics.Stopwatch.Frequency,
                                slowestCircularVesselName
                                );

                sb.AppendFormat(Tools.SIFormatter, "\n\tKerbin LOS check: {0:S3}s",
                                (double)totalKerbinLOSTicks / (double)System.Diagnostics.Stopwatch.Frequency
                                );

                sb.AppendFormat(Tools.SIFormatter, "\n\tStatus resolution check: {0:S3}s",
                                (double)statusResolutionTicks / (double)System.Diagnostics.Stopwatch.Frequency
                                );

                // sb.AppendFormat(Tools.SIFormatter, "", start)

                this.LogWarning(sb.ToString());

                Tools.PutStringBuilder(sb);
            }
                        #endif
        }
Esempio n. 9
0
        // Runs on start.
        public override void OnStart(StartState state)
        {
            using (PooledDebugLogger log = PooledDebugLogger.New(this))
            {
                                #if DEBUG
                try {
                                #endif

                log.AppendFormat("{0}: starting up", this.ToString());

                // Start up the underlying PartModule stuff.
                base.OnStart(state);

                log.Append("\n\tbase started up");

                ModuleReactionWheel prefabModule;

                // Fetch the reaction wheel module.
                if (this.part.tryGetFirstModuleOfType <ModuleReactionWheel>(out this.reactionWheelModule))
                {
                    log.AppendFormat("\n\tFound ModuleReactionWheel {0}", this.reactionWheelModule);

                    if (PartLoader.getPartInfoByName(this.part.partInfo.name).partPrefab
                        .tryGetFirstModuleOfType <ModuleReactionWheel>(out prefabModule))
                    {
                        log.AppendFormat("\n\tFound prefab module {0}", prefabModule);

                        TweakableTools.InitializeTweakable <ModuleTweakableReactionWheel>(
                            this.Fields["RollTorque"].uiControlCurrent(),
                            ref this.RollTorque,
                            ref this.reactionWheelModule.RollTorque,
                            prefabModule.RollTorque
                            );

                        log.Append("\n\tRollTorque setup");

                        TweakableTools.InitializeTweakable <ModuleTweakableReactionWheel>(
                            this.Fields["PitchTorque"].uiControlCurrent(),
                            ref this.PitchTorque,
                            ref this.reactionWheelModule.PitchTorque,
                            prefabModule.PitchTorque
                            );

                        log.Append("\n\tPitchTorque setup");

                        TweakableTools.InitializeTweakable <ModuleTweakableReactionWheel>(
                            this.Fields["YawTorque"].uiControlCurrent(),
                            ref this.YawTorque,
                            ref this.reactionWheelModule.YawTorque,
                            prefabModule.YawTorque
                            );

                        log.Append("\n\tYawTorque setup");
                    }
                }

                var torqueGainCtl = this.Fields["TorqueGain"].uiControlCurrent();

                if (torqueGainCtl is UI_FloatRange)
                {
                    var torqueGainSlider = torqueGainCtl as UI_FloatRange;

                    torqueGainSlider.maxValue      = 1f;
                    torqueGainSlider.stepIncrement = 0.025f;
                }

                log.Append("\n\tStarted!");
                                #if DEBUG
            } finally {
                log.Print();
            }
                                #endif
            }
        }