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); } }
public void OnDestroy() { using (PooledDebugLogger logger = PooledDebugLogger.New(this)) { logger.Append("Destroying..."); this.CloseFileIfOpen(); logger.Append(" Done."); logger.Print(false); } }
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; }
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 ); }
/// <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 }
// 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 } }