/// <summary>
 /// Copy Constructor.
 /// </summary>
 /// <param name="orig"></param>
 public SpawnVessel(SpawnVessel orig)
 {
     foreach (VesselData vd in orig.vessels)
     {
         vessels.Add(new VesselData(vd));
     }
 }
예제 #2
0
        /// <summary>
        /// Copy Constructor.
        /// </summary>
        /// <param name="orig"></param>
        public SpawnVessel(SpawnVessel orig)
        {
            deferVesselCreation = orig.deferVesselCreation;
            foreach (VesselData vessel in orig.vessels)
            {
                if (vessel.pqsCity != null)
                {
                    // Generate PQS city coordinates
                    LoggingUtil.LogVerbose(this, "Generating coordinates from PQS city for Vessel " + vessel.name);

                    // Translate by the PQS offset (inverse transform of coordinate system)
                    Vector3d position = vessel.pqsCity.transform.position;
                    LoggingUtil.LogVerbose(this, "    pqs city position = " + position);
                    Vector3d v = vessel.pqsOffset;
                    Vector3d i = vessel.pqsCity.transform.right;
                    Vector3d j = vessel.pqsCity.transform.forward;
                    Vector3d k = vessel.pqsCity.transform.up;
                    LoggingUtil.LogVerbose(this, "    i, j, k = " + i + ", " + j + "," + k);
                    Vector3d offsetPos = new Vector3d(
                        (j.y * k.z - j.z * k.y) * v.x + (i.z * k.y - i.y * k.z) * v.y + (i.y * j.z - i.z * j.y) * v.z,
                        (j.z * k.x - j.x * k.z) * v.x + (i.x * k.z - i.z * k.x) * v.y + (i.z * j.x - i.x * j.z) * v.z,
                        (j.x * k.y - j.y * k.x) * v.x + (i.y * k.x - i.x * k.y) * v.y + (i.x * j.y - i.y * j.x) * v.z
                        );
                    offsetPos       *= (i.x * j.y * k.z) + (i.y * j.z * k.x) + (i.z * j.x * k.y) - (i.z * j.y * k.x) - (i.y * j.x * k.z) - (i.x * j.z * k.y);
                    vessel.latitude  = vessel.body.GetLatitude(position + offsetPos);
                    vessel.longitude = vessel.body.GetLongitude(position + offsetPos);
                    LoggingUtil.LogVerbose(this, "    resulting lat, lon = (" + vessel.latitude + ", " + vessel.longitude + ")");
                }

                vessels.Add(new VesselData(vessel));
            }
        }
        /// <summary>
        /// Copy Constructor.
        /// </summary>
        /// <param name="orig"></param>
        public SpawnVessel(SpawnVessel orig)
        {
            deferVesselCreation = orig.deferVesselCreation;
            foreach (VesselData vessel in orig.vessels)
            {
                if (vessel.pqsCity != null)
                {
                    // Generate PQS city coordinates
                    LoggingUtil.LogVerbose(this, "Generating coordinates from PQS city for Vessel " + vessel.name);

                    // Translate by the PQS offset (inverse transform of coordinate system)
                    Vector3d position = vessel.pqsCity.transform.position;
                    LoggingUtil.LogVerbose(this, "    pqs city position = " + position);
                    Vector3d v = vessel.pqsOffset;
                    Vector3d i = vessel.pqsCity.transform.right;
                    Vector3d j = vessel.pqsCity.transform.forward;
                    Vector3d k = vessel.pqsCity.transform.up;
                    LoggingUtil.LogVerbose(this, "    i, j, k = " + i + ", " + j + "," + k);
                    Vector3d offsetPos = new Vector3d(
                        (j.y * k.z - j.z * k.y) * v.x + (i.z * k.y - i.y * k.z) * v.y + (i.y * j.z - i.z * j.y) * v.z,
                        (j.z * k.x - j.x * k.z) * v.x + (i.x * k.z - i.z * k.x) * v.y + (i.z * j.x - i.x * j.z) * v.z,
                        (j.x * k.y - j.y * k.x) * v.x + (i.y * k.x - i.x * k.y) * v.y + (i.x * j.y - i.y * j.x) * v.z
                    );
                    offsetPos *= (i.x * j.y * k.z) + (i.y * j.z * k.x) + (i.z * j.x * k.y) - (i.z * j.y * k.x) - (i.y * j.x * k.z) - (i.x * j.z * k.y);
                    vessel.latitude = vessel.body.GetLatitude(position + offsetPos);
                    vessel.longitude = vessel.body.GetLongitude(position + offsetPos);
                    LoggingUtil.LogVerbose(this, "    resulting lat, lon = (" + vessel.latitude + ", " + vessel.longitude + ")");
                }

                vessels.Add(new VesselData(vessel));
            }
        }
 /// <summary>
 /// Copy Constructor.
 /// </summary>
 /// <param name="orig"></param>
 public SpawnVessel(SpawnVessel orig)
 {
     deferVesselCreation = orig.deferVesselCreation;
     foreach (VesselData vd in orig.vessels)
     {
         vessels.Add(new VesselData(vd));
     }
 }
        public override bool Load(ConfigNode configNode)
        {
            // Load base class
            bool valid = base.Load(configNode);

            // Call SpawnKerbal for load behaviour
            spawnVessel = SpawnVessel.Create(configNode, this);

            return valid && spawnVessel != null;
        }
예제 #6
0
        public override bool Load(ConfigNode configNode)
        {
            // Load base class
            bool valid = base.Load(configNode);

            // Call SpawnKerbal for load behaviour
            spawnVessel = SpawnVessel.Create(configNode, this);

            return(valid && spawnVessel != null);
        }
예제 #7
0
        public static SpawnVessel Create(ConfigNode configNode, SpawnVesselFactory factory)
        {
            SpawnVessel spawnVessel = new SpawnVessel();

            ConfigNodeUtil.ParseValue <bool>(configNode, "deferVesselCreation", x => spawnVessel.deferVesselCreation = x, factory, false);

            bool valid = true;
            int  index = 0;

            foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL"))
            {
                DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory);
                try
                {
                    ConfigNodeUtil.SetCurrentDataNode(dataNode);

                    VesselData vessel = new VesselData();

                    // Get name
                    if (child.HasValue("name"))
                    {
                        valid &= ConfigNodeUtil.ParseValue <string>(child, "name", x => vessel.name = x, factory);
                    }

                    // Get craft details
                    if (child.HasValue("craftURL"))
                    {
                        valid &= ConfigNodeUtil.ParseValue <string>(child, "craftURL", x => vessel.craftURL = x, factory);
                    }
                    if (child.HasValue("craftPart"))
                    {
                        valid &= ConfigNodeUtil.ParseValue <AvailablePart>(child, "craftPart", x => vessel.craftPart = x, factory);
                    }
                    valid &= ConfigNodeUtil.AtLeastOne(child, new string[] { "craftURL", "craftPart" }, factory);

                    valid &= ConfigNodeUtil.ParseValue <string>(child, "flagURL", x => vessel.flagURL = x, factory, (string)null);
                    valid &= ConfigNodeUtil.ParseValue <VesselType>(child, "vesselType", x => vessel.vesselType = x, factory, VesselType.Ship);

                    // Use an expression to default - then it'll work for dynamic contracts
                    if (!child.HasValue("targetBody"))
                    {
                        child.AddValue("targetBody", "@/targetBody");
                    }
                    valid &= ConfigNodeUtil.ParseValue <CelestialBody>(child, "targetBody", x => vessel.body = x, factory);

                    // Get landed stuff
                    if (child.HasValue("pqsCity"))
                    {
                        string pqsCityStr = null;
                        valid &= ConfigNodeUtil.ParseValue <string>(child, "pqsCity", x => pqsCityStr = x, factory);
                        if (pqsCityStr != null)
                        {
                            try
                            {
                                vessel.pqsCity = vessel.body.GetComponentsInChildren <PQSCity>(true).Where(pqs => pqs.name == pqsCityStr).First();
                            }
                            catch (Exception e)
                            {
                                LoggingUtil.LogError(typeof(WaypointGenerator), "Couldn't load PQSCity with name '" + pqsCityStr + "'");
                                LoggingUtil.LogException(e);
                                valid = false;
                            }
                        }
                        valid &= ConfigNodeUtil.ParseValue <Vector3d>(child, "pqsOffset", x => vessel.pqsOffset = x, factory, new Vector3d());

                        // Don't expect these to load anything, but do it to mark as initialized
                        valid &= ConfigNodeUtil.ParseValue <double>(child, "lat", x => vessel.latitude = x, factory, 0.0);
                        valid &= ConfigNodeUtil.ParseValue <double>(child, "lon", x => vessel.longitude = x, factory, 0.0);

                        // Do load alt and height
                        valid &= ConfigNodeUtil.ParseValue <double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null);
                        valid &= ConfigNodeUtil.ParseValue <float>(child, "height", x => vessel.height = x, factory,
                                                                   !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f);
                        vessel.orbiting = false;
                    }
                    else if (child.HasValue("lat") && child.HasValue("lon"))
                    {
                        valid &= ConfigNodeUtil.ParseValue <double>(child, "lat", x => vessel.latitude = x, factory);
                        valid &= ConfigNodeUtil.ParseValue <double>(child, "lon", x => vessel.longitude = x, factory);
                        valid &= ConfigNodeUtil.ParseValue <double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null);
                        valid &= ConfigNodeUtil.ParseValue <float>(child, "height", x => vessel.height = x, factory,
                                                                   !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f);
                        vessel.orbiting = false;
                    }
                    // Get orbit
                    else
                    {
                        valid          &= ConfigNodeUtil.ParseValue <Orbit>(child, "ORBIT", x => vessel.orbit = x, factory);
                        vessel.orbiting = true;
                    }

                    valid &= ConfigNodeUtil.ParseValue <float>(child, "heading", x => vessel.heading = x, factory, 0.0f);
                    valid &= ConfigNodeUtil.ParseValue <float>(child, "pitch", x => vessel.pitch = x, factory, 0.0f);
                    valid &= ConfigNodeUtil.ParseValue <float>(child, "roll", x => vessel.roll = x, factory, 0.0f);

                    // Get additional flags
                    valid &= ConfigNodeUtil.ParseValue <bool>(child, "owned", x => vessel.owned = x, factory, false);

                    // Handle the CREW nodes
                    foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW"))
                    {
                        int count = 1;
                        valid &= ConfigNodeUtil.ParseValue <int>(crewNode, "count", x => count = x, factory, 1);
                        for (int i = 0; i < count; i++)
                        {
                            CrewData cd = new CrewData();

                            // Read crew details
                            valid &= ConfigNodeUtil.ParseValue <string>(crewNode, "name", x => cd.name = x, factory, (string)null);
                            valid &= ConfigNodeUtil.ParseValue <bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true);

                            // Check for unexpected values
                            valid &= ConfigNodeUtil.ValidateUnexpectedValues(crewNode, factory);

                            // Add the record
                            vessel.crew.Add(cd);
                        }
                    }

                    // Check for unexpected values
                    valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory);

                    // Add to the list
                    spawnVessel.vessels.Add(vessel);
                }
                finally
                {
                    ConfigNodeUtil.SetCurrentDataNode(factory.dataNode);
                }
            }

            if (!configNode.HasNode("VESSEL"))
            {
                valid = false;
                LoggingUtil.LogError(factory, "SpawnVessel requires at least one VESSEL node.");
            }

            return(valid ? spawnVessel : null);
        }
        public static SpawnVessel Create(ConfigNode configNode, SpawnVesselFactory factory)
        {
            SpawnVessel spawnVessel = new SpawnVessel();

            ConfigNodeUtil.ParseValue<bool>(configNode, "deferVesselCreation", x => spawnVessel.deferVesselCreation = x, factory, false);

            bool valid = true;
            int index = 0;
            foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL"))
            {
                DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory);
                try
                {
                    ConfigNodeUtil.SetCurrentDataNode(dataNode);

                    VesselData vessel = new VesselData();

                    // Get name
                    if (child.HasValue("name"))
                    {
                        valid &= ConfigNodeUtil.ParseValue<string>(child, "name", x => vessel.name = x, factory);
                    }

                    // Get craft details
                    if (child.HasValue("craftURL"))
                    {
                        valid &= ConfigNodeUtil.ParseValue<string>(child, "craftURL", x => vessel.craftURL = x, factory);
                    }
                    if (child.HasValue("craftPart"))
                    {
                        valid &= ConfigNodeUtil.ParseValue<AvailablePart>(child, "craftPart", x => vessel.craftPart = x, factory);
                    }
                    valid &= ConfigNodeUtil.AtLeastOne(child, new string[] { "craftURL", "craftPart" }, factory);

                    valid &= ConfigNodeUtil.ParseValue<string>(child, "flagURL", x => vessel.flagURL = x, factory, (string)null);
                    valid &= ConfigNodeUtil.ParseValue<VesselType>(child, "vesselType", x => vessel.vesselType = x, factory, VesselType.Ship);

                    // Use an expression to default - then it'll work for dynamic contracts
                    if (!child.HasValue("targetBody"))
                    {
                        child.AddValue("targetBody", "@/targetBody");
                    }
                    valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => vessel.body = x, factory);

                    // Get landed stuff
                    if (child.HasValue("pqsCity"))
                    {
                        string pqsCityStr = null;
                        valid &= ConfigNodeUtil.ParseValue<string>(child, "pqsCity", x => pqsCityStr = x, factory);
                        if (pqsCityStr != null)
                        {
                            try
                            {
                                vessel.pqsCity = vessel.body.GetComponentsInChildren<PQSCity>(true).Where(pqs => pqs.name == pqsCityStr).First();
                            }
                            catch (Exception e)
                            {
                                LoggingUtil.LogError(typeof(WaypointGenerator), "Couldn't load PQSCity with name '" + pqsCityStr + "'");
                                LoggingUtil.LogException(e);
                                valid = false;
                            }
                        }
                        valid &= ConfigNodeUtil.ParseValue<Vector3d>(child, "pqsOffset", x => vessel.pqsOffset = x, factory, new Vector3d());

                        // Don't expect these to load anything, but do it to mark as initialized
                        valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory, 0.0);
                        valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory, 0.0);

                        // Do load alt and height
                        valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null);
                        valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory,
                            !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f);
                        vessel.orbiting = false;

                        // Generate PQS city coordinates
                        LoggingUtil.LogVerbose(factory, "Generating coordinates from PQS city for Vessel " + vessel.name);

                        // Translate by the PQS offset (inverse transform of coordinate system)
                        Vector3d position = vessel.pqsCity.transform.position;
                        Vector3d v = vessel.pqsOffset;
                        Vector3d i = vessel.pqsCity.transform.right;
                        Vector3d j = vessel.pqsCity.transform.forward;
                        Vector3d k = vessel.pqsCity.transform.up;
                        Vector3d offsetPos = new Vector3d(
                            (j.y * k.z - j.z * k.y) * v.x + (i.z * k.y - i.y * k.z) * v.y + (i.y * j.z - i.z * j.y) * v.z,
                            (j.z * k.x - j.x * k.z) * v.x + (i.x * k.z - i.z * k.x) * v.y + (i.z * j.x - i.x * j.z) * v.z,
                            (j.x * k.y - j.y * k.x) * v.x + (i.y * k.x - i.x * k.y) * v.y + (i.x * j.y - i.y * j.x) * v.z
                        );
                        offsetPos *= (i.x * j.y * k.z) + (i.y * j.z * k.x) + (i.z * j.x * k.y) - (i.z * j.y * k.x) - (i.y * j.x * k.z) - (i.x * j.z * k.y);
                        vessel.latitude = vessel.body.GetLatitude(position + offsetPos);
                        vessel.longitude = vessel.body.GetLongitude(position + offsetPos);
                    }
                    else if (child.HasValue("lat") && child.HasValue("lon"))
                    {
                        valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory);
                        valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory);
                        valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null);
                        valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory,
                            !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f);
                        vessel.orbiting = false;
                    }
                    // Get orbit
                    else
                    {
                        valid &= ConfigNodeUtil.ParseValue<Orbit>(child, "ORBIT", x => vessel.orbit = x, factory);
                        vessel.orbiting = true;
                    }

                    valid &= ConfigNodeUtil.ParseValue<float>(child, "heading", x => vessel.heading = x, factory, 0.0f);
                    valid &= ConfigNodeUtil.ParseValue<float>(child, "pitch", x => vessel.pitch = x, factory, 0.0f);
                    valid &= ConfigNodeUtil.ParseValue<float>(child, "roll", x => vessel.roll = x, factory, 0.0f);

                    // Get additional flags
                    valid &= ConfigNodeUtil.ParseValue<bool>(child, "owned", x => vessel.owned = x, factory, false);

                    // Handle the CREW nodes
                    foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW"))
                    {
                        int count = 1;
                        valid &= ConfigNodeUtil.ParseValue<int>(crewNode, "count", x => count = x, factory, 1);
                        for (int i = 0; i < count; i++)
                        {
                            CrewData cd = new CrewData();

                            // Read crew details
                            valid &= ConfigNodeUtil.ParseValue<string>(crewNode, "name", x => cd.name = x, factory, (string)null);
                            valid &= ConfigNodeUtil.ParseValue<bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true);

                            // Check for unexpected values
                            valid &= ConfigNodeUtil.ValidateUnexpectedValues(crewNode, factory);

                            // Add the record
                            vessel.crew.Add(cd);
                        }
                    }

                    // Check for unexpected values
                    valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory);

                    // Add to the list
                    spawnVessel.vessels.Add(vessel);
                }
                finally
                {
                    ConfigNodeUtil.SetCurrentDataNode(factory.dataNode);
                }
            }

            if (!configNode.HasNode("VESSEL"))
            {
                valid = false;
                LoggingUtil.LogError(factory, "SpawnVessel requires at least one VESSEL node.");
            }

            return valid ? spawnVessel : null;
        }
        public static SpawnVessel Create(ConfigNode configNode, SpawnVesselFactory factory)
        {
            SpawnVessel spawnVessel = new SpawnVessel();

            ConfigNodeUtil.ParseValue<bool>(configNode, "deferVesselCreation", x => spawnVessel.deferVesselCreation = x, factory, false);

            bool valid = true;
            int index = 0;
            foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL"))
            {
                DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory);
                try
                {
                    ConfigNodeUtil.SetCurrentDataNode(dataNode);

                    VesselData vessel = new VesselData();

                    // Get name
                    if (child.HasValue("name"))
                    {
                        valid &= ConfigNodeUtil.ParseValue<string>(child, "name", x => vessel.name = x, factory);
                    }

                    // Get craft details
                    if (child.HasValue("craftURL"))
                    {
                        valid &= ConfigNodeUtil.ParseValue<string>(child, "craftURL", x => vessel.craftURL = x, factory);
                    }
                    if (child.HasValue("craftPart"))
                    {
                        valid &= ConfigNodeUtil.ParseValue<AvailablePart>(child, "craftPart", x => vessel.craftPart = x, factory);
                    }
                    valid &= ConfigNodeUtil.AtLeastOne(child, new string[] { "craftURL", "craftPart" }, factory);

                    valid &= ConfigNodeUtil.ParseValue<string>(child, "flagURL", x => vessel.flagURL = x, factory, (string)null);
                    valid &= ConfigNodeUtil.ParseValue<VesselType>(child, "vesselType", x => vessel.vesselType = x, factory, VesselType.Ship);

                    // Use an expression to default - then it'll work for dynamic contracts
                    if (!child.HasValue("targetBody"))
                    {
                        child.AddValue("targetBody", "@/targetBody");
                    }
                    valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => vessel.body = x, factory);

                    // Get landed stuff
                    if (child.HasValue("lat") && child.HasValue("lon"))
                    {
                        valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory);
                        valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory);
                        valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null);
                        valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory,
                            !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f);
                        vessel.orbiting = false;
                    }
                    // Get orbit
                    else
                    {
                        valid &= ConfigNodeUtil.ParseValue<Orbit>(child, "ORBIT", x => vessel.orbit = x, factory);
                        vessel.orbiting = true;
                    }

                    valid &= ConfigNodeUtil.ParseValue<float>(child, "heading", x => vessel.heading = x, factory, 0.0f);
                    valid &= ConfigNodeUtil.ParseValue<float>(child, "pitch", x => vessel.pitch = x, factory, 0.0f);
                    valid &= ConfigNodeUtil.ParseValue<float>(child, "roll", x => vessel.roll = x, factory, 0.0f);

                    // Get additional flags
                    valid &= ConfigNodeUtil.ParseValue<bool>(child, "owned", x => vessel.owned = x, factory, false);

                    // Handle the CREW nodes
                    foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW"))
                    {
                        int count = 1;
                        valid &= ConfigNodeUtil.ParseValue<int>(crewNode, "count", x => count = x, factory, 1);
                        for (int i = 0; i < count; i++)
                        {
                            CrewData cd = new CrewData();

                            // Read crew details
                            valid &= ConfigNodeUtil.ParseValue<string>(crewNode, "name", x => cd.name = x, factory, (string)null);
                            valid &= ConfigNodeUtil.ParseValue<bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true);

                            // Check for unexpected values
                            valid &= ConfigNodeUtil.ValidateUnexpectedValues(crewNode, factory);

                            // Add the record
                            vessel.crew.Add(cd);
                        }
                    }

                    // Check for unexpected values
                    valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory);

                    // Add to the list
                    spawnVessel.vessels.Add(vessel);
                }
                finally
                {
                    ConfigNodeUtil.SetCurrentDataNode(factory.dataNode);
                }
            }

            if (!configNode.HasNode("VESSEL"))
            {
                valid = false;
                LoggingUtil.LogError(factory, "SpawnVessel requires at least one VESSEL node.");
            }

            return valid ? spawnVessel : null;
        }
        public static SpawnVessel Create(ConfigNode configNode, CelestialBody defaultBody, SpawnVesselFactory factory)
        {
            SpawnVessel spawnVessel = new SpawnVessel();

            bool valid = true;
            int  index = 0;

            foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL"))
            {
                DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory);
                try
                {
                    ConfigNodeUtil.SetCurrentDataNode(dataNode);

                    VesselData vessel = new VesselData();

                    // Get name
                    if (child.HasValue("name"))
                    {
                        vessel.name = child.GetValue("name");
                    }

                    // Get paths
                    vessel.craftURL   = ConfigNodeUtil.ParseValue <string>(child, "craftURL");
                    vessel.flagURL    = ConfigNodeUtil.ParseValue <string>(child, "flagURL", (string)null);
                    vessel.vesselType = ConfigNodeUtil.ParseValue <VesselType>(child, "vesselType", VesselType.Ship);

                    // Get celestial body
                    valid &= ConfigNodeUtil.ParseValue <CelestialBody>(child, "targetBody", x => vessel.body = x, factory, defaultBody, Validation.NotNull);

                    // Get landed stuff
                    if (child.HasValue("lat") && child.HasValue("lon"))
                    {
                        valid        &= ConfigNodeUtil.ParseValue <double>(child, "lat", x => vessel.latitude = x, factory);
                        valid        &= ConfigNodeUtil.ParseValue <double>(child, "lon", x => vessel.longitude = x, factory);
                        valid        &= ConfigNodeUtil.ParseValue <double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null);
                        vessel.landed = true;
                    }
                    // Get orbit
                    else
                    {
                        valid       &= ConfigNodeUtil.ValidateMandatoryChild(child, "ORBIT", factory);
                        vessel.orbit = new OrbitSnapshot(ConfigNodeUtil.GetChildNode(child, "ORBIT")).Load();
                        vessel.orbit.referenceBody = vessel.body;
                    }

                    // Get additional flags
                    valid &= ConfigNodeUtil.ParseValue <bool>(child, "owned", x => vessel.owned = x, factory, false);

                    // Handle the CREW nodes
                    foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW"))
                    {
                        int count = 1;
                        valid &= ConfigNodeUtil.ParseValue <int>(crewNode, "count", x => count = x, factory, 1);
                        for (int i = 0; i < count; i++)
                        {
                            CrewData cd = new CrewData();

                            // Read crew details
                            valid &= ConfigNodeUtil.ParseValue <string>(crewNode, "name", x => cd.name = x, factory, (string)null);
                            valid &= ConfigNodeUtil.ParseValue <bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true);

                            // Add the record
                            vessel.crew.Add(cd);
                        }
                    }

                    // Add to the list
                    spawnVessel.vessels.Add(vessel);
                }
                finally
                {
                    ConfigNodeUtil.SetCurrentDataNode(factory.dataNode);
                }
            }

            return(valid ? spawnVessel : null);
        }