static IEnumerator WaitAndMakeLonePart(Part newPart, OnPartReady onPartReady)
        {
            Debug.Log("[ModuleMissileRearm]: Create lone part vessel for {0}" + newPart);
            string originatingVesselName = newPart.vessel.vesselName;

            newPart.physicalSignificance = Part.PhysicalSignificance.NONE;
            newPart.PromoteToPhysicalPart();
            newPart.Unpack();
            newPart.disconnect(true);
            Vessel newVessel = newPart.gameObject.AddComponent <Vessel>();

            newVessel.id = Guid.NewGuid();
            if (newVessel.Initialize(false))
            {
                newVessel.vesselName = Vessel.AutoRename(newVessel, originatingVesselName);
                newVessel.IgnoreGForces(10);
                newVessel.currentStage = StageManager.RecalculateVesselStaging(newVessel);
                newPart.setParent(null);
            }
            yield return(new WaitWhile(() => !newPart.started && newPart.State != PartStates.DEAD));

            Debug.Log("[ModuleMissileRearm]: Part {0} is in state {1}" + newPart + newPart.State);
            if (newPart.State == PartStates.DEAD)
            {
                Debug.Log("[ModuleMissileRearm]: Part {0} has died before fully instantiating" + newPart);
                yield break;
            }

            if (onPartReady != null)
            {
                onPartReady(newPart);
            }
        }
        static IEnumerator WaitAndCouple(Part newPart, string srcAttachNodeId,
                                         AttachNode tgtAttachNode, OnPartReady onPartReady,
                                         bool createPhysicsless = false)
        {
            var tgtPart = newPart.parent;

            if (createPhysicsless)
            {
                newPart.PhysicsSignificance = 1;  // Disable physics on the part.
            }

            // Create proper attach nodes.
            Debug.Log("[ModuleMissileRearm]: Attach new part {0} to {1}: srcNodeId={2}, tgtNode={3}" +
                      newPart + newPart.vessel +
                      srcAttachNodeId);
            var srcAttachNode = GetAttachNodeById(newPart, srcAttachNodeId);

            srcAttachNode.attachedPart   = tgtPart;
            srcAttachNode.attachedPartId = tgtPart.flightID;
            if (tgtAttachNode != null)
            {
                tgtAttachNode.attachedPart   = newPart;
                tgtAttachNode.attachedPartId = newPart.flightID;
            }

            // When target, source or both are docking ports force them into state PreAttached. It's the
            // most safe state that simulates behavior of parts attached in the editor.
            var srcDockingNode = GetDockingNode(newPart, attachNodeId: srcAttachNodeId);

            if (srcDockingNode != null)
            {
                // Source part is not yet started. It's functionality is very limited.
                srcDockingNode.state                  = "PreAttached";
                srcDockingNode.dockedPartUId          = 0;
                srcDockingNode.dockingNodeModuleIndex = 0;
                Debug.Log("[ModuleMissileRearm]: Force new node {0} to state {1}" + newPart + srcDockingNode.state);
            }
            var tgtDockingNode = GetDockingNode(tgtPart, attachNode: tgtAttachNode);

            if (tgtDockingNode != null)
            {
                CoupleDockingPortWithPart(tgtDockingNode);
            }

            // Wait until part is started. Keep it in position till it happen.
            Debug.Log("[ModuleMissileRearm]: Wait for part {0} to get alive...", newPart);
            newPart.transform.parent = tgtPart.transform;
            var relPos = newPart.transform.localPosition;
            var relRot = newPart.transform.localRotation;

            if (newPart.PhysicsSignificance != 1)
            {
                // Mangling with colliders on physicsless parts may result in camera effects.
                var childColliders = newPart.GetComponentsInChildren <Collider>(includeInactive: false);
                CollisionManager.IgnoreCollidersOnVessel(tgtPart.vessel, childColliders);
            }
            while (!newPart.started && newPart.State != PartStates.DEAD)
            {
                yield return(new WaitForFixedUpdate());

                if (newPart.rb != null)
                {
                    newPart.rb.position        = newPart.parent.transform.TransformPoint(relPos);
                    newPart.rb.rotation        = newPart.parent.transform.rotation * relRot;
                    newPart.rb.velocity        = newPart.parent.Rigidbody.velocity;
                    newPart.rb.angularVelocity = newPart.parent.Rigidbody.angularVelocity;
                }
            }
            newPart.transform.parent = newPart.transform;
            Debug.Log("[ModuleMissileRearm]: Part {0} is in state {1}" + newPart + newPart.State);
            if (newPart.State == PartStates.DEAD)
            {
                Debug.Log("[ModuleMissileRearm]: Part {0} has died before fully instantiating", newPart);
                yield break;
            }

            // Complete part initialization.
            newPart.Unpack();
            newPart.InitializeModules();

            // Notify game about a new part that has just "coupled".
            GameEvents.onPartCouple.Fire(new GameEvents.FromToAction <Part, Part>(newPart, tgtPart));
            tgtPart.vessel.ClearStaging();
            GameEvents.onVesselPartCountChanged.Fire(tgtPart.vessel);
            newPart.vessel.checkLanded();
            newPart.vessel.currentStage = StageManager.RecalculateVesselStaging(tgtPart.vessel) + 1;
            GameEvents.onVesselWasModified.Fire(tgtPart.vessel);
            newPart.CheckBodyLiftAttachment();

            if (onPartReady != null)
            {
                onPartReady(newPart);
            }
        }
        /// <summary>Creates a new part from the config.</summary>
        /// <param name="partConfig">Config to read part from.</param>
        /// <param name="position">Initial position of the new part.</param>
        /// <param name="rotation">Initial rotation of the new part.</param>
        /// <param name="fromPart"></param>
        /// <param name="coupleToPart">Optional. Part to couple new part to.</param>
        /// <param name="srcAttachNodeId">
        /// Optional. Attach node ID on the new part to use for coupling. It's required if coupling to
        /// part is requested.
        /// </param>
        /// <param name="tgtAttachNode">
        /// Optional. Attach node on the target part to use for coupling. It's required if
        /// <paramref name="srcAttachNodeId"/> specifies a stack node.
        /// </param>
        /// <param name="onPartReady">
        /// Callback to call when new part is fully operational and its joint is created (if any). It's
        /// undetermined how long it may take before the callback is called. The calling code must expect
        /// that there will be several frame updates and at least one fixed frame update.
        /// </param>
        /// <param name="createPhysicsless">
        /// Tells if new part must be created without rigidbody and joint. It's only used to create
        /// equippable parts. Any other use-case is highly unlikely.
        /// </param>
        /// <returns></returns>
        public static Part CreatePart(
            ConfigNode partConfig,
            Vector3 position,
            Quaternion rotation,
            Part fromPart,
            Part coupleToPart        = null,
            string srcAttachNodeId   = null,
            AttachNode tgtAttachNode = null,
            OnPartReady onPartReady  = null,
            bool createPhysicsless   = false)
        {
            // Sanity checks for the parameters.
            if (coupleToPart != null)
            {
                if (srcAttachNodeId == null ||
                    srcAttachNodeId == "srfAttach" && tgtAttachNode != null ||
                    srcAttachNodeId != "srfAttach" &&
                    (tgtAttachNode == null || tgtAttachNode.id == "srfAttach"))
                {
                    // Best we can do is falling back to surface attach.
                    srcAttachNodeId = "srfAttach";
                    tgtAttachNode   = null;
                }
            }

            var refVessel    = coupleToPart != null ? coupleToPart.vessel : fromPart.vessel;
            var partNodeCopy = new ConfigNode();

            partConfig.CopyTo(partNodeCopy);
            var snapshot =
                new ProtoPartSnapshot(partNodeCopy, refVessel.protoVessel, HighLogic.CurrentGame);

            if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) ||
                snapshot.flightID == 0)
            {
                snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            }
            snapshot.parentIdx = coupleToPart != null?refVessel.parts.IndexOf(coupleToPart) : 0;

            snapshot.position            = position;
            snapshot.rotation            = rotation;
            snapshot.stageIndex          = 0;
            snapshot.defaultInverseStage = 0;
            snapshot.seqOverride         = -1;
            snapshot.inStageIndex        = -1;
            snapshot.attachMode          = srcAttachNodeId == "srfAttach"
                ? (int)AttachModes.SRF_ATTACH
                : (int)AttachModes.STACK;
            snapshot.attached = true;
            snapshot.flagURL  = fromPart.flagURL;

            var newPart = snapshot.Load(refVessel, false);

            refVessel.Parts.Add(newPart);
            newPart.transform.position = position;
            newPart.transform.rotation = rotation;
            newPart.missionID          = fromPart.missionID;
            newPart.UpdateOrgPosAndRot(newPart.vessel.rootPart);

            if (coupleToPart != null)
            {
                // Wait for part to initialize and then fire ready event.
                Debug.Log("[ModuleMissileRearm]: Ready to error" + newPart + srcAttachNodeId + tgtAttachNode);
                newPart.StartCoroutine(
                    WaitAndCouple(newPart, srcAttachNodeId, tgtAttachNode, onPartReady,
                                  createPhysicsless: createPhysicsless));
            }
            else
            {
                // Create new part as a separate vessel.
                newPart.StartCoroutine(WaitAndMakeLonePart(newPart, onPartReady));
            }
            return(newPart);
        }