Exemple #1
0
 /// <inheritdoc/>
 public virtual void OnKASNodeBlockedState(ILinkPeer ownerPeer, bool isBlocked)
 {
     if (ownerPeer.cfgAttachNodeName == attachNodeName ||
         cfgDependentNodeNames.Contains(ownerPeer.cfgAttachNodeName))
     {
         // This is a notification handler, so don't use the isNodeBlocked property to not trigger
         // more notifications.
         //FIXME: fix the comment when migrated to the setter methods.
         linkState = isBlocked ? LinkState.NodeIsBlocked : LinkState.Available;
     }
 }
Exemple #2
0
        /// <summary>Helper method to create a part's context menu.</summary>
        /// <param name="peer">The peer module to create an action for.</param>
        /// <param name="guiName">The GUI name of the menu item.</param>
        /// <param name="action">The action to exectue when the menu item is triggered.</param>
        /// <returns>The new event. It's not automatically injected into the part.</returns>
        BaseEvent MakeEvent(ILinkPeer peer, Message guiName, Action <ILinkPeer> action)
        {
            var ev = new BaseEvent(
                peer.part.Events,
                "autoEventAttach" + peer.part.Modules.IndexOf(peer as PartModule),
                () => action.Invoke(peer),
                new KSPEvent());

            ev.guiActive          = true;
            ev.guiActiveUncommand = true;
            ev.guiActiveUnfocused = true;
            ev.guiName            = guiName;
            return(ev);
        }
Exemple #3
0
        /// <inheritdoc/>
        public ILinkPeer FindLinkPeer(ILinkPeer srcPeer)
        {
            var host    = srcPeer as PartModule;
            var tgtPart = FlightGlobals.FindPartByID(srcPeer.linkPartId);

            if (tgtPart == null)
            {
                HostedDebugLog.Warning(host, "Cannot find target part: partId=F{0}", srcPeer.linkPartId);
                return(null);
            }

            // In normal case we can lookup by the node name.
            ILinkPeer tgtPeer = null;

            if (!string.IsNullOrEmpty(srcPeer.linkNodeName))
            {
                tgtPeer = tgtPart.Modules
                          .OfType <ILinkPeer>()
                          .FirstOrDefault(m => m.linkState == LinkState.Linked &&
                                          m.linkPartId == srcPeer.part.flightID &&
                                          m.linkNodeName == srcPeer.cfgAttachNodeName &&
                                          m.cfgLinkType == srcPeer.cfgLinkType);
            }

            // Fallback case. Try guessing the target peer by less strict conditions.
            if (tgtPeer == null)
            {
                var candidates = tgtPart.Modules
                                 .OfType <ILinkPeer>()
                                 .Where(m => m.linkState == LinkState.Linked &&
                                        m.linkPartId == srcPeer.part.flightID &&
                                        m.cfgLinkType == srcPeer.cfgLinkType)
                                 .ToList();
                if (candidates.Count == 1)
                {
                    tgtPeer = candidates[0];
                    HostedDebugLog.Warning(host, "FALLBACK: Found a link: {0} => {1}", srcPeer, tgtPeer);
                }
            }

            if (tgtPeer == null)
            {
                HostedDebugLog.Warning(
                    host,
                    "Failed to find the link: targetPartId={0}, targetNode={1}",
                    srcPeer.linkPartId, srcPeer.linkNodeName);
            }
            return(tgtPeer);
        }
 bool CheckKASLink(ILinkPeer peer)
 {
     if (peer.isLinked && peer.otherPeer != null)
     {
         var thisVessel  = peer.part.vessel;
         var otherVessel = peer.otherPeer.part.vessel;
         if (thisVessel != otherVessel &&
             !visitedVessels.Contains(otherVessel.id))
         {
             visitedVessels.Add(otherVessel.id);
             ProcessParts(otherVessel.parts[0].localRoot, AddModule(otherVessel.vesselName));
             return(true);
         }
     }
     return(false);
 }
Exemple #5
0
        /// <summary>Sets the opposite point of the link.</summary>
        /// <param name="peer">
        /// The other endpoint. It's <c>null</c> when the endpoint must be reset.
        /// </param>
        /// <seealso cref="otherPeer"/>
        protected virtual void SetOtherPeer(ILinkPeer peer)
        {
            var oldPeer = _otherPeer;

            _otherPeer = peer;
            if (_otherPeer != null)
            {
                persistedLinkPartId   = _otherPeer != null ? _otherPeer.part.flightID : 0;
                persistedLinkNodeName = _otherPeer.cfgAttachNodeName;
            }
            else
            {
                persistedLinkPartId   = 0;
                persistedLinkNodeName = "";
            }
            OnPeerChange(oldPeer);
        }
 bool CheckKASLink(ILinkPeer peer)
 {
     if (addVessels && peer.isLinked && peer.otherPeer != null)
     {
         var thisVessel  = peer.part.vessel;
         var otherVessel = peer.otherPeer.part.vessel;
         if (!excludeParts.Contains(peer.otherPeer.part) &&
             thisVessel != otherVessel &&
             !visitedVessels.Contains(otherVessel.id))
         {
             visitedVessels.Add(otherVessel.id);
             AddVessel(otherVessel.vesselName, otherVessel.parts,
                       otherVessel.parts[0].localRoot);
             return(true);
         }
     }
     return(false);
 }
Exemple #7
0
        /// <summary>
        /// Removes the linked connector from the kerbal and links it to the target part.
        /// </summary>
        /// <param name="peer">The target part link module.</param>
        void LinkCarriedConnector(ILinkPeer peer)
        {
            var target = peer as ILinkTarget;

            if (target != null && isLinked &&
                linkSource.CheckCanLinkTo(target, checkStates: false, reportToGUI: true))
            {
                var source = linkSource;
                source.BreakCurrentLink(LinkActorType.API);
                if (!source.LinkToTarget(LinkActorType.Player, target))
                {
                    UISoundPlayer.instance.Play(KASAPI.CommonConfig.sndPathBipWrong);
                }
            }
            else
            {
                UISoundPlayer.instance.Play(KASAPI.CommonConfig.sndPathBipWrong);
            }
        }
Exemple #8
0
        /// <inheritdoc/>
        public ILinkPeer FindLinkPeer(ILinkPeer srcPeer)
        {
            if (srcPeer.linkPartId == 0 || srcPeer.linkModuleIndex == -1)
            {
                DebugEx.Error("Bad target part definition [Part:(id=F{0}#Module:{1}]",
                              srcPeer.linkPartId, srcPeer.linkModuleIndex);
                return(null);
            }
            var tgtPart = FlightGlobals.FindPartByID(srcPeer.linkPartId);

            if (tgtPart == null)
            {
                DebugEx.Error("Cannot find [Part:(id=F{0})]", srcPeer.linkPartId);
                return(null);
            }
            if (srcPeer.linkModuleIndex >= tgtPart.Modules.Count)
            {
                DebugEx.Error("The target part {0} doesn't have a module at index {1}",
                              tgtPart, srcPeer.linkModuleIndex);
                return(null);
            }
            var tgtPeer = tgtPart.Modules[srcPeer.linkModuleIndex] as ILinkPeer;

            if (tgtPeer == null)
            {
                DebugEx.Error("The target module {0} is not a link peer",
                              tgtPart.Modules[srcPeer.linkModuleIndex]);
                return(null);
            }
            if (!tgtPeer.isLinked || tgtPeer.linkPartId != srcPeer.part.flightID ||
                tgtPeer.linkModuleIndex != srcPeer.part.Modules.IndexOf(srcPeer as PartModule))
            {
                DebugEx.Error("Source module {0} cannot be linked with the target module {1}",
                              srcPeer.part.Modules[tgtPeer.linkModuleIndex],
                              tgtPart.Modules[srcPeer.linkModuleIndex]);
                return(null);
            }
            return(tgtPeer);
        }
Exemple #9
0
        /// <inheritdoc/>
        protected override void OnPeerChange(ILinkPeer oldPeer)
        {
            base.OnPeerChange(oldPeer);
            linkState = linkSource != null ? LinkState.Linked : LinkState.Available;

            // Trigger events on the part.
            var oldSource = oldPeer as ILinkSource;

            if (linkStateMachine.currentState != null && oldSource != linkSource)
            {
                var linkInfo = new KasLinkEventImpl(linkSource ?? oldSource, this);
                if (linkSource != null)
                {
                    part.Modules.OfType <ILinkStateEventListener>().ToList()
                    .ForEach(x => x.OnKASLinkedState(linkInfo, isLinked: true));
                }
                else
                {
                    part.Modules.OfType <ILinkStateEventListener>().ToList()
                    .ForEach(x => x.OnKASLinkedState(linkInfo, isLinked: false));
                }
            }
        }
Exemple #10
0
 /// <inheritdoc/>
 public void OnKASNodeBlockedState(ILinkPeer ownerPeer, bool isBlocked)
 {
     throw new NotImplementedException(); // Obsolete.
 }
Exemple #11
0
 /// <summary>Triggers when a linked peers has been assigned with a value.</summary>
 /// <remarks>
 /// This method triggers even when the new peer doesn't differ from the old one. When it's
 /// important to catch the transition, check for the <paramref name="oldPeer"/>.
 /// </remarks>
 /// <param name="oldPeer">The peer prior to the change.</param>
 protected virtual void OnPeerChange(ILinkPeer oldPeer)
 {
 }
Exemple #12
0
 /// <summary>Checks if the peers are coupled via their attach nodes.</summary>
 /// <param name="source">The peer the link.</param>
 /// <param name="target">The peer the link.</param>
 /// <returns><c>true</c> if the peers are coupled.</returns>
 static bool CheckCoupled(ILinkPeer source, ILinkPeer target)
 {
     return(source.coupleNode != null && source.coupleNode.attachedPart == target.part &&
            target.coupleNode != null && target.coupleNode.attachedPart == source.part);
 }
        //FIXME rework for multiple connections
        ConnectedPartSet ConnectedParts(Part part)
        {
            var connectedParts = new ConnectedPartSet();

            for (int i = part.Modules.Count; i-- > 0;)
            {
                var module = part.Modules[i];
                // This covers radial and stack decouplers and separators,
                // launch clamps, and docking ports.
                var separator = module as IStageSeparator;
                if (separator != null)
                {
                    GetOtherPart(separator, connectedParts);
                    continue;
                }

                // The claw is on its own as it is never staged (I guess).
                var grapple = module as ModuleGrappleNode;
                if (grapple != null)
                {
                    GetOtherPart(grapple, connectedParts);
                    continue;
                }

                // EL's launchpad module is very much on its own. No need
                // to worry about survey stations as the built vessel is
                // never attached, nor disposable pads as they self
                // destruct.
                var pad = module as ELLaunchpad;
                if (pad != null)
                {
                    GetOtherPart(pad, connectedParts);
                    continue;
                }

                //FIXME need to add KAS connectors
                if (module.moduleName == "KASModuleStrut")
                {
                    // legacy pipe connector
                    var kasStrut = new KASModuleStrut(module);
                    GetOtherPart(kasStrut, connectedParts);
                    continue;
                }

                if (module.moduleName == "KASLinkResourceConnector")
                {
                    // new resoruce connector. works when undocked!
                    // however, can be used to dock the vessel, in which
                    // case KASJointCableBase is to be checked, or even
                    // just connected on the same vessel (just ignore)
                    var peer = new ILinkPeer(module);
                    if (CheckKASLink(peer))
                    {
                        continue;
                    }
                }

                if (module.moduleName == "KASLinkTargetBase")
                {
                    // new resoruce connector. works when undocked!
                    // however, can be used to dock the vessel, in which
                    // case KASJointCableBase is to be checked, or even
                    // just connected on the same vessel (just ignore)
                    var peer = new ILinkPeer(module);
                    if (peer.cfgLinkType == "MdHose" && CheckKASLink(peer))
                    {
                        continue;
                    }
                }

                if (module.moduleName == "KASJointCableBase")
                {
                    var kasJoint = new KASJointCableBase(module);
                    GetOtherPart(kasJoint, connectedParts);
                }
            }
            return(connectedParts);
        }
Exemple #14
0
 /// <summary>Checks if the peer parts are coupled in the vessel hierarchy.</summary>
 /// <param name="source">The first peer of the link.</param>
 /// <param name="target">The other peer of the link.</param>
 /// <returns><c>true</c> if the peers are coupled.</returns>
 static bool CheckCoupled(ILinkPeer source, ILinkPeer target)
 {
     return(source.part.parent == target.part || target.part.parent == source.part);
 }