/// <summary>
        /// Registers all the ContractRequirement classes.
        /// </summary>
        void RegisterContractRequirements()
        {
            LoggingUtil.LogDebug(this, "Start Registering ContractRequirements");

            // Register each type
            foreach (Type subclass in GetAllTypes <ContractRequirement>().Where(t => !t.IsAbstract))
            {
                string name = subclass.Name;
                if (name.EndsWith("Requirement"))
                {
                    name = name.Remove(name.Length - 11, 11);
                }

                try
                {
                    ContractRequirement.Register(subclass, name);
                }
                catch (Exception e)
                {
                    LoggingUtil.LogError(this, "Error registering contract requirement " + subclass.Name);
                    LoggingUtil.LogException(e);
                }
            }

            LoggingUtil.LogInfo(this, "Finished Registering ContractRequirements");
        }
        /// <summary>
        /// Registers all the BehaviourFactory classes.
        /// </summary>
        void RegisterBehaviourFactories()
        {
            LoggingUtil.LogDebug(this, "Start Registering BehaviourFactories");

            // Register each type with the behaviour factory
            foreach (Type subclass in GetAllTypes <BehaviourFactory>().Where(t => !t.IsAbstract))
            {
                string name = subclass.Name;
                if (name.EndsWith("Factory"))
                {
                    name = name.Remove(name.Length - 7, 7);
                }

                try
                {
                    BehaviourFactory.Register(subclass, name);
                }
                catch (Exception e)
                {
                    LoggingUtil.LogError(this, "Error registering behaviour factory " + subclass.Name);
                    LoggingUtil.LogException(e);
                }
            }

            LoggingUtil.LogInfo(this, "Finished Registering BehaviourFactories");
        }
Example #3
0
        protected override void OnSave(ConfigNode node)
        {
            try
            {
                node.AddValue("subtype", subType);
                node.AddValue("title", title);
                node.AddValue("description", description);
                node.AddValue("synopsis", synopsis);
                node.AddValue("completedMessage", completedMessage);
                node.AddValue("notes", notes);
                node.AddValue("hash", hash);

                foreach (ContractBehaviour behaviour in behaviours)
                {
                    ConfigNode child = new ConfigNode("BEHAVIOUR");
                    behaviour.Save(child);
                    node.AddNode(child);
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error saving contract to persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_SAVE, e, this);

                SetState(State.Failed);
            }
        }
Example #4
0
        public override void OnLoad(ConfigNode node)
        {
            try
            {
                foreach (ConfigNode child in node.GetNodes("CONTRACT"))
                {
                    ConfiguredContract contract = null;
                    try
                    {
                        contract = new ConfiguredContract();
                        Contract.Load(contract, child);
                    }
                    catch (Exception e)
                    {
                        LoggingUtil.LogWarning(this, "Ignored an exception while trying to load a pre-loaded contract:");
                        LoggingUtil.LogException(e);
                    }

                    if (contract != null && contract.contractType != null)
                    {
                        contract.preLoaded = true;
                        contracts.Add(contract);
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading ContractPreLoader from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_LOAD, e, "ContractPreLoader");
            }
        }
Example #5
0
        public override void OnSave(ConfigNode node)
        {
            try
            {
                base.OnSave(node);

                ConfigNode dataNode = new ConfigNode("DATA");
                node.AddNode(dataNode);

                // Handle individual values
                foreach (KeyValuePair <string, System.Object> p in data)
                {
                    StoreToConfigNode(dataNode, p.Key, p.Value);
                }

                // Handle config nodes
                foreach (ConfigNode childNode in configNodes.Values)
                {
                    dataNode.AddNode(childNode);
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error saving PersistentDataStore to persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_SAVE, e, "PersistentDataStore");
            }
        }
        public override void OnSave(ConfigNode node)
        {
            try
            {
                foreach (ConfiguredContract contract in contracts.Where(c => c.ContractState == Contract.State.Offered))
                {
                    ConfigNode child = new ConfigNode("CONTRACT");
                    node.AddNode(child);
                    contract.Save(child);
                }

                ConfigNode unreadNode = new ConfigNode("UNREAD_CONTRACTS");
                node.AddNode(unreadNode);
                foreach (Contract c in ContractSystem.Instance.Contracts.Where(c => unreadContracts.Contains(c.ContractGuid)))
                {
                    unreadNode.AddValue("contract", c.ContractGuid);
                }
                foreach (ConfiguredContract c in contracts.Where(c => unreadContracts.Contains(c.ContractGuid)))
                {
                    unreadNode.AddValue("contract", c.ContractGuid);
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error saving ContractPreLoader to persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_SAVE, e, "ContractPreLoader");
            }
        }
Example #7
0
        protected override bool Generate()
        {
            // Special case for pre-loader
            if (ContractState == State.Withdrawn)
            {
                return(true);
            }

            try
            {
                if (contractType != null)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error generating contract!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_GENERATION, e,
                                                         contractType == null ? "unknown" : contractType.FullName);

                try
                {
                    GenerateFailed();
                }
                catch { }

                return(false);
            }
        }
Example #8
0
        public static IEnumerable <Type> GetAllTypes <T>()
        {
            // Get everything that extends the given type
            List <Type> allTypes = new List <Type>();

            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                IEnumerable <Type> types = null;
                try
                {
                    types = from type in assembly.GetTypes() where (type.IsSubclassOf(typeof(T)) || type.GetInterface(typeof(T).Name) != null) select type;
                }
                catch (Exception e)
                {
                    LoggingUtil.LogException(new Exception("Error loading types from assembly " + assembly.FullName, e));
                    continue;
                }

                foreach (Type t in types)
                {
                    Type foundType = t;

                    if (foundType != null)
                    {
                        yield return(foundType);
                    }
                }
            }
        }
Example #9
0
        public override void OnLoad(ConfigNode node)
        {
            try
            {
                lastMCButton            = ConfigNodeUtil.ParseValue <MissionControlButton>(node, "lastMCButton", MissionControlButton.All);
                DisplayOfferedOrbits    = ConfigNodeUtil.ParseValue <bool?>(node, "DisplayOfferedOrbits", (bool?)ContractDefs.DisplayOfferedOrbits).Value;
                DisplayOfferedWaypoints = ConfigNodeUtil.ParseValue <bool?>(node, "DisplayOfferedWaypoints", (bool?)ContractDefs.DisplayOfferedWaypoints).Value;
                DisplayActiveOrbits     = ConfigNodeUtil.ParseValue <bool?>(node, "DisplayActiveOrbits", (bool?)true).Value;
                DisplayActiveWaypoints  = ConfigNodeUtil.ParseValue <bool?>(node, "DisplayActiveWaypoints", (bool?)true).Value;

                foreach (ConfigNode groupNode in node.GetNodes("CONTRACT_GROUP"))
                {
                    string groupName = groupNode.GetValue("group");

                    if (ContractGroup.contractGroups.ContainsKey(groupName))
                    {
                        ContractGroup group = ContractGroup.contractGroups[groupName];

                        ContractGroupDetails details = new ContractGroupDetails(group);
                        details.enabled = ConfigNodeUtil.ParseValue <bool>(groupNode, "enabled");

                        contractGroupDetails[group.name] = details;
                    }
                    else
                    {
                        LoggingUtil.LogWarning(this, "Couldn't find contract group with name '" + groupName + "'");
                    }
                }

                foreach (ConfigNode stateNode in node.GetNodes("CONTRACT_STATE"))
                {
                    string typeName = stateNode.GetValue("type");
                    if (!string.IsNullOrEmpty(typeName))
                    {
                        Type contractType = null;
                        try
                        {
                            contractType = ConfigNodeUtil.ParseTypeValue(typeName);
                            StockContractDetails details = new StockContractDetails(contractType);
                            details.enabled = ConfigNodeUtil.ParseValue <bool>(stateNode, "enabled");

                            stockContractDetails[contractType] = details;

                            ContractDisabler.SetContractState(contractType, details.enabled);
                        }
                        catch (ArgumentException)
                        {
                            LoggingUtil.LogWarning(this, "Couldn't find contract type with name '" + typeName + "'");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading ContractConfiguratorSettings from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_LOAD, e, "ContractConfiguratorSettings");
            }
        }
        /// <summary>
        /// Loads all the contact configuration group nodes.
        /// </summary>
        private IEnumerator <YieldInstruction> LoadGroupConfig()
        {
            // Load all the contract groups
            LoggingUtil.LogDebug(this, "Loading CONTRACT_GROUP nodes.");
            ConfigNode[] contractGroups = GameDatabase.Instance.GetConfigNodes("CONTRACT_GROUP");

            foreach (ConfigNode groupConfig in contractGroups)
            {
                // Create the group
                string name = groupConfig.GetValue("name");
                LoggingUtil.LogInfo(this, "Loading CONTRACT_GROUP: '" + name + "'");
                ContractGroup contractGroup = null;
                try
                {
                    contractGroup = new ContractGroup(name);
                }
                catch (ArgumentException)
                {
                    LoggingUtil.LogError(this, "Couldn't load CONTRACT_GROUP '" + name + "' due to a duplicate name.");
                }

                // Peform the actual load
                if (contractGroup != null)
                {
                    bool success = false;
                    try
                    {
                        ConfigNodeUtil.ClearCache(true);
                        success = contractGroup.Load(groupConfig);
                    }
                    catch (Exception e)
                    {
                        Exception wrapper = new Exception("Error loading CONTRACT_GROUP '" + name + "'", e);
                        LoggingUtil.LogException(wrapper);
                    }
                    finally
                    {
                        if (!success)
                        {
                            ContractGroup.contractGroups.Remove(name);
                        }
                    }
                }
            }

            if (!reloading)
            {
                yield return(new WaitForEndOfFrame());
            }

            // Emit settings for the menu
            SettingsBuilder.EmitSettings();

            yield break;
        }
Example #11
0
        public override void OnLoad(ConfigNode node)
        {
            try
            {
                base.OnLoad(node);

                ConfigNode dataNode = node.GetNode("DATA");
                if (dataNode != null)
                {
                    // Handle individual values
                    foreach (ConfigNode.Value pair in dataNode.values)
                    {
                        string typeName = pair.value.Remove(pair.value.IndexOf(":"));
                        string value    = pair.value.Substring(typeName.Length + 1);
                        Type   type     = ConfigNodeUtil.ParseTypeValue(typeName);

                        if (type == typeof(string))
                        {
                            data[pair.name] = value;
                        }
                        else if (type.Name == "List`1")
                        {
                            BaseParser parser = BaseParser.NewParser(type);
                            if (parser == null)
                            {
                                throw new Exception("Couldn't read list of values of type '" + type.GetGenericArguments().First().Name + "'.");
                            }
                            data[pair.name] = parser.ParseExpressionGeneric("", value, null);
                        }
                        else
                        {
                            // Get the ParseValue method
                            MethodInfo parseValueMethod = typeof(ConfigNodeUtil).GetMethods().Where(m => m.Name == "ParseSingleValue").Single();
                            parseValueMethod = parseValueMethod.MakeGenericMethod(new Type[] { type });

                            // Invoke the ParseValue method
                            data[pair.name] = parseValueMethod.Invoke(null, new object[] { pair.name, value, false });
                        }
                    }

                    // Handle config nodes
                    foreach (ConfigNode childNode in dataNode.GetNodes())
                    {
                        configNodes[childNode.name] = childNode;
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading PersistentDataStore from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_LOAD, e, "PersistentDataStore");
            }
        }
Example #12
0
 public override void OnLoad(ConfigNode node)
 {
     try
     {
         Load();
     }
     catch (Exception e)
     {
         LoggingUtil.LogError(this, "Error loading BiomeTracker data from custom file!");
         LoggingUtil.LogException(e);
         ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_LOAD, e, "BiomeTracker");
     }
 }
        /// <summary>
        /// Validates the given SCANname and sees if SCANsat has a SCANtype that matches it.
        /// </summary>
        /// <param name="SCANname">The SCANname to validate.</param>
        /// <returns>Whether the validation succeeded, outputs an error if it did not.</returns>
        public static bool ValidateSCANname(string SCANname)
        {
            try
            {
                GetSCANtype(SCANname);
            }
            catch (Exception e)
            {
                LoggingUtil.LogException(e);
                return(false);
            }

            return(true);
        }
Example #14
0
        public override void OnSave(ConfigNode node)
        {
            try
            {
                base.OnSave(node);

                foreach (KeyValuePair <string, VesselInfo> p in vessels)
                {
                    VesselInfo vi = p.Value;

                    // First find the vessel by id
                    Vessel vessel = FlightGlobals.Vessels.Find(v => v != null && v.id == vi.id);

                    if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                    {
                        // If not found, attempt to find it by hash
                        if (vessel == null)
                        {
                            vessel = FlightGlobals.Vessels.Find(v => v != null && v.GetHashes().Contains(vi.hash));
                        }
                        // If found, verify the hash
                        else
                        {
                            IEnumerable <uint> hashes = vessel.GetHashes();
                            if (hashes.Any() && !hashes.Contains(vi.hash))
                            {
                                LoggingUtil.LogVerbose(this, "Setting hash for " + vi.id + " on save from " + vi.hash + " to " + hashes.FirstOrDefault());
                                vi.hash = hashes.FirstOrDefault();
                            }
                        }
                    }

                    if (vessel != null)
                    {
                        ConfigNode child = new ConfigNode("VESSEL");
                        child.AddValue("key", p.Key);
                        child.AddValue("id", vi.id);
                        child.AddValue("hash", vi.hash);
                        node.AddNode(child);
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error saving ContractVesselTracker to persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_SAVE, e, "ContractVesselTracker");
            }
        }
Example #15
0
        protected override void OnLoad(ConfigNode node)
        {
            try
            {
                subType          = node.GetValue("subtype");
                contractType     = string.IsNullOrEmpty(subType) ? null : ContractType.GetContractType(subType);
                title            = ConfigNodeUtil.ParseValue <string>(node, "title", contractType != null ? contractType.title : subType);
                description      = ConfigNodeUtil.ParseValue <string>(node, "description", contractType != null ? contractType.description : "");
                synopsis         = ConfigNodeUtil.ParseValue <string>(node, "synopsis", contractType != null ? contractType.synopsis : "");
                completedMessage = ConfigNodeUtil.ParseValue <string>(node, "completedMessage", contractType != null ? contractType.completedMessage : "");
                notes            = ConfigNodeUtil.ParseValue <string>(node, "notes", contractType != null ? contractType.notes : "");
                hash             = ConfigNodeUtil.ParseValue <int>(node, "hash", contractType != null ? contractType.hash : 0);

                foreach (ConfigNode child in node.GetNodes("BEHAVIOUR"))
                {
                    ContractBehaviour behaviour = ContractBehaviour.LoadBehaviour(child, this);
                    behaviours.Add(behaviour);
                }

                // If the contract type is null, then it likely means that it was uninstalled
                if (contractType == null)
                {
                    LoggingUtil.LogWarning(this, "Error loading contract for contract type '" + subType +
                                           "'.  The contract type either failed to load or was uninstalled.");
                    try
                    {
                        SetState(State.Failed);
                    }
                    catch { }
                    return;
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading contract from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_LOAD, e, this);

                try
                {
                    SetState(State.Failed);
                }
                catch { }
            }
        }
        public override void OnSave(ConfigNode node)
        {
            try
            {
                base.OnSave(node);

                foreach (ScienceSubject s in trackedSubjects)
                {
                    node.AddValue("subject", s.id);
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error saving ScienceReporter to persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_SAVE, e, "ScienceReporter");
            }
        }
Example #17
0
 public override void OnSave(ConfigNode node)
 {
     try
     {
         foreach (ConfiguredContract contract in contracts.Where(c => c.ContractState == Contract.State.Offered))
         {
             ConfigNode child = new ConfigNode("CONTRACT");
             node.AddNode(child);
             contract.Save(child);
         }
     }
     catch (Exception e)
     {
         LoggingUtil.LogError(this, "Error saving ContractPreLoader to persistance file!");
         LoggingUtil.LogException(e);
         ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_SAVE, e, "ContractPreLoader");
     }
 }
Example #18
0
        /// <summary>
        /// Checks if all the given ContractRequirement meet the requirement.
        /// </summary>
        /// <param name="contract">Contract to check</param>
        /// <param name="contractType">Contract type of the contract (in case the contract type has not yet been assigned).</param>
        /// <param name="contractRequirements">The list of requirements to check</param>
        /// <returns>Whether the requirement is met or not.</returns>
        public static bool RequirementsMet(ConfiguredContract contract, ContractType contractType, IEnumerable <ContractRequirement> contractRequirements)
        {
            bool allReqMet = true;

            try
            {
                LoggingUtil.LogVerbose(typeof(ContractRequirement), "Checking requirements for contract '{0}'", contractType.name);
                foreach (ContractRequirement requirement in contractRequirements)
                {
                    if (requirement.enabled)
                    {
                        if (requirement.checkOnActiveContract || contract == null || contract.ContractState != Contract.State.Active)
                        {
                            allReqMet = allReqMet && requirement.CheckRequirement(contract);

                            if (!allReqMet)
                            {
                                LoggingUtil.Log(contract != null && contract.ContractState == Contract.State.Active ? LoggingUtil.LogLevel.INFO :
                                                contract != null && contract.ContractState == Contract.State.Offered ? LoggingUtil.LogLevel.DEBUG : LoggingUtil.LogLevel.VERBOSE,
                                                requirement.GetType(), "Contract {0}: requirement {1} was not met.", contractType.name, requirement.name);
                                break;
                            }
                        }
                    }
                }

                // Force fail the contract if a requirement becomes unmet
                if (contract != null && contract.ContractState == Contract.State.Active && !allReqMet)
                {
                    // Fail the contract - unfortunately, the player won't know why. :(
                    contract.Fail();

                    // Force the stock contracts window to refresh
                    GameEvents.Contract.onContractsLoaded.Fire();
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogException(new Exception("ContractConfigurator: Exception checking requirements!", e));
                return(false);
            }
            return(allReqMet);
        }
        public override bool LoadFromConfig(ConfigNode configNode)
        {
            // Before loading, verify the SCANsat version
            if (!SCANsatUtil.VerifySCANsatVersion())
            {
                return(false);
            }

            // Load base class
            bool valid = base.LoadFromConfig(configNode);

            // Do not check the requirement on active contracts.  Otherwise when they scan the
            // contract is invalidated, which is usually not what's meant.
            checkOnActiveContract = false;

            valid &= ConfigNodeUtil.ParseValue <string>(configNode, "scanType", x => scanType = x, this, "Anomaly", SCANsatUtil.ValidateSCANname);
            valid &= ConfigNodeUtil.ParseValue <double>(configNode, "latitude", x => latitude = x, this, 0.0);
            valid &= ConfigNodeUtil.ParseValue <double>(configNode, "longitude", x => longitude = x, this, 0.0);

            valid &= ConfigNodeUtil.MutuallyExclusive(configNode, new string[] { "latitude", "longitude" }, new string[] { "pqsCity" }, this);
            valid &= ValidateTargetBody(configNode);

            string pqsName = null;

            valid &= ConfigNodeUtil.ParseValue <string>(configNode, "pqsCity", x => pqsName = x, this, (string)null);
            if (pqsName != null)
            {
                try
                {
                    pqsCity = targetBody.GetComponentsInChildren <PQSCity>(true).Where(pqs => pqs.name == pqsName).First();
                }
                catch (Exception e)
                {
                    LoggingUtil.LogError(this, "Couldn't load PQSCity with name '" + pqsCity + "'");
                    LoggingUtil.LogException(e);
                    valid = false;
                }
            }

            return(valid);
        }
Example #20
0
        public override void OnLoad(ConfigNode node)
        {
            try
            {
                base.OnLoad(node);

                ConfigNode dataNode = node.GetNode("DATA");
                if (dataNode != null)
                {
                    // Handle individual values
                    foreach (ConfigNode.Value pair in dataNode.values)
                    {
                        string typeName = pair.value.Remove(pair.value.IndexOf(":"));
                        string value    = pair.value.Substring(typeName.Length + 1, pair.value.Length - typeName.Length - 1);
                        Type   type     = Type.GetType(typeName);
                        if (type == typeof(string))
                        {
                            data[pair.name] = pair.value;
                        }
                        else
                        {
                            data[pair.name] = type.InvokeMember("Parse", System.Reflection.BindingFlags.InvokeMethod, null, null, new string[] { value });
                        }
                    }

                    // Handle config nodes
                    foreach (ConfigNode childNode in dataNode.GetNodes())
                    {
                        configNodes[childNode.name] = childNode;
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading PersistentDataStore from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_LOAD, e, "PersistentDataStore");
            }
        }
        public override void OnLoad(ConfigNode node)
        {
            try
            {
                base.OnLoad(node);

                foreach (string id in node.GetValuesList("subject"))
                {
                    ScienceSubject s = ResearchAndDevelopment.GetSubjectByID(id);
                    if (s != null)
                    {
                        trackedSubjects.Add(s);
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading ScienceReporter from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_LOAD, e, "ScienceReporter");
            }
        }
        public override void OnLoad(ConfigNode node)
        {
            try
            {
                base.OnLoad(node);

                foreach (ConfigNode child in node.GetNodes("VESSEL"))
                {
                    string key  = child.GetValue("key");
                    Guid   id   = new Guid(child.GetValue("id"));
                    uint   hash = ConfigNodeUtil.ParseValue <uint>(child, "hash", 0);

                    StartCoroutine(CompleteVesselLoad(key, id));
                    vessels[key] = new VesselInfo(id, hash);
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading ContractVesselTracker from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_LOAD, e, "ContractVesselTracker");
            }
        }
Example #23
0
        public override void OnLoad(ConfigNode node)
        {
            try
            {
                base.OnLoad(node);

                foreach (ConfigNode child in node.GetNodes("VESSEL"))
                {
                    string key  = child.GetValue("key");
                    Guid   id   = new Guid(child.GetValue("id"));
                    uint   hash = ConfigNodeUtil.ParseValue <uint>(child, "hash", 0);

                    Vessel vessel = FlightGlobals.Vessels.Find(v => v != null && v.id == id);
                    if (vessel == null || vessel.state == Vessel.State.DEAD)
                    {
                        id = Guid.Empty;
                    }
                    else if (hash == 0 && HighLogic.LoadedScene == GameScenes.FLIGHT)
                    {
                        hash = vessel.GetHashes().FirstOrDefault();
                        LoggingUtil.LogVerbose(this, "Setting hash for " + id + " on load to: " + hash);
                    }

                    if (id != Guid.Empty)
                    {
                        vessels[key] = new VesselInfo(id, hash);
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading ContractVesselTracker from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_LOAD, e, "ContractVesselTracker");
            }
        }
Example #24
0
        public override void OnSave(ConfigNode node)
        {
            try
            {
                node.AddValue("lastMCButton", lastMCButton);

                node.AddValue("DisplayOfferedOrbits", DisplayOfferedOrbits);
                node.AddValue("DisplayOfferedWaypoints", DisplayOfferedWaypoints);
                node.AddValue("DisplayActiveOrbits", DisplayActiveOrbits);
                node.AddValue("DisplayActiveWaypoints", DisplayActiveWaypoints);

                foreach (ContractGroupDetails details in contractGroupDetails.Values.Where(d => d.group != null))
                {
                    ConfigNode groupNode = new ConfigNode("CONTRACT_GROUP");
                    node.AddNode(groupNode);

                    groupNode.AddValue("group", details.group.name);
                    groupNode.AddValue("enabled", details.enabled);
                }

                foreach (StockContractDetails details in stockContractDetails.Values.Where(d => d.contractType != null))
                {
                    ConfigNode stateNode = new ConfigNode("CONTRACT_STATE");
                    node.AddNode(stateNode);

                    stateNode.AddValue("type", details.contractType.Name);
                    stateNode.AddValue("enabled", details.enabled);
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error saving ContractConfiguratorSettings to persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.SCENARIO_MODULE_SAVE, e, "ContractConfiguratorSettings");
            }
        }
Example #25
0
        /// <summary>
        /// Attempts to parse a value from the config node.  Returns a default value if not found.
        /// Validates return values using the given function.
        /// </summary>
        /// <typeparam name="T">The type of value to convert to.</typeparam>
        /// <param name="configNode">The ConfigNode to read from.</param>
        /// <param name="key">The key to examine.</param>
        /// <param name="setter">Function used to set the output value</param>
        /// <param name="obj">Factory object for error messages.</param>
        /// <param name="defaultValue">Default value to use if there is no key in the config node</param>
        /// <param name="validation">Validation function to run against the returned value</param>
        /// <returns>The parsed value (or default value if not found)</returns>
        public static bool ParseValue <T>(ConfigNode configNode, string key, Action <T> setter, IContractConfiguratorFactory obj, T defaultValue, Func <T, bool> validation)
        {
            // Initialize the data type of the expression
            if (currentDataNode != null && !currentDataNode.IsInitialized(key))
            {
                currentDataNode.BlankInit(key, typeof(T));
            }

            bool valid = true;
            T    value = defaultValue;

            if (configNode.HasValue(key) || configNode.HasNode(key))
            {
                try
                {
                    // Check whether there's a value
                    if (configNode.HasValue(key) && string.IsNullOrEmpty(configNode.GetValue(key)))
                    {
                        LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": Required value '" + key + "' is empty.");
                        valid = false;
                    }
                    else
                    {
                        // Load value
                        value = ParseValue <T>(configNode, key, true);
                    }

                    // If value was non-null, run validation
                    if (value != null && (typeof(T) != typeof(string) || ((string)(object)value) != ""))
                    {
                        try
                        {
                            valid = validation.Invoke(value);
                            if (!valid)
                            {
                                // In general, the validation function should throw an exception and give a much better message
                                LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": A validation error occured while loading the key '" + key + "' with value '" + value + "'.");
                            }
                        }
                        catch (Exception e)
                        {
                            if (e is DataNode.ValueNotInitialized)
                            {
                                throw;
                            }

                            LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": A validation error occured while loading the key '" + key + "' with value '" + value + "'.");
                            LoggingUtil.LogException(e);
                            valid = false;
                        }
                    }
                }
                catch (Exception e)
                {
                    if (e.GetType() == typeof(DataNode.ValueNotInitialized))
                    {
                        string dependency = ((DataNode.ValueNotInitialized)e).key;
                        string path       = currentDataNode.Path() + key;

                        LoggingUtil.LogVerbose(typeof(ConfigNodeUtil), "Trying to load " + path + ", but " + dependency + " is uninitialized.");

                        // Defer loading this value
                        DeferredLoadObject <T> loadObj = null;
                        if (!deferredLoads.ContainsKey(path) || deferredLoads[path].GetType().GetGenericArguments().First() != typeof(T))
                        {
                            deferredLoads[path] = new DeferredLoadObject <T>(configNode, key, setter, obj, validation, currentDataNode);
                        }
                        loadObj = (DeferredLoadObject <T>)deferredLoads[path];

                        // New dependency - try again
                        if (!loadObj.dependencies.Contains(dependency))
                        {
                            LoggingUtil.LogVerbose(typeof(ConfigNodeUtil), "    New dependency, will re-attempt to load later.");
                            loadObj.dependencies.Add(dependency);
                            return(true);
                        }
                    }

                    LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": Error parsing " + key);

                    // Return immediately on deferred load error
                    if (e.GetType() == typeof(DataNode.ValueNotInitialized))
                    {
                        DataNode.ValueNotInitialized vni = e as DataNode.ValueNotInitialized;
                        LoggingUtil.LogException(new Exception("Unknown identifier '@" + vni.key + "'."));
                        return(false);
                    }
                    LoggingUtil.LogException(e);

                    valid = false;
                }
                finally
                {
                    AddFoundKey(configNode, key);
                }
            }

            // Store the value
            if (currentDataNode != null)
            {
                currentDataNode[key] = value;

                if (!currentDataNode.IsDeterministic(key) && initialLoad)
                {
                    currentDataNode.DeferredLoads.Add(new DeferredLoadObject <T>(configNode, key, setter, obj, validation, currentDataNode));
                }
            }

            // Invoke the setter function
            if (valid)
            {
                setter.Invoke(value);
            }

            return(valid);
        }
Example #26
0
        /// <summary>
        /// Parses a value from a config node.
        /// </summary>
        /// <typeparam name="T">The type to convert to.</typeparam>
        /// <param name="configNode">The ConfigNode to read from</param>
        /// <param name="key">The key to examine.</param>
        /// <param name="allowExpression">Whether the read value can be an expression.</param>
        /// <returns>The parsed value</returns>
        public static T ParseValue <T>(ConfigNode configNode, string key, bool allowExpression = false)
        {
            // Check for required value
            if (!configNode.HasValue(key))
            {
                if (configNode.HasNode(key))
                {
                    return(ParseNode <T>(configNode, key, allowExpression));
                }
                else
                {
                    throw new ArgumentException("Missing required value '" + key + "'.");
                }
            }

            // Special cases
            if (typeof(T).Name == "List`1")
            {
                int count = configNode.GetValues(key).Count();

                // Special handling to try and load the list all at once
                if (count == 1 && allowExpression)
                {
                    try
                    {
                        return(ParseSingleValue <T>(key, configNode.GetValue(key), allowExpression));
                    }
                    catch (Exception e)
                    {
                        Exception handled = e;
                        while (handled != null && handled.GetType() == typeof(Exception))
                        {
                            handled = handled.InnerException;
                        }

                        // Exceptions we explicitly ignore
                        if (handled == null ||
                            handled.GetType() != typeof(DataStoreCastException) &&
                            handled.GetType() != typeof(NotSupportedException) &&
                            handled.GetType() != typeof(ArgumentNullException) &&
                            handled.GetType() != typeof(InvalidCastException))
                        {
                            // Exceptions we explicitly rethrow
                            if (handled != null && handled.GetType() == typeof(DataNode.ValueNotInitialized))
                            {
                                throw;
                            }

                            // The rest gets logged
                            LoggingUtil.LogWarning(typeof(ConfigNodeUtil), "Got an unexpected exception trying to load '" + key + "' as a list:");
                            LoggingUtil.LogException(e);
                        }

                        // And continue on to load the standard way
                    }
                }

                // Create the list instance
                T list = (T)Activator.CreateInstance(typeof(T));

                // Create the generic methods
                MethodInfo parseValueMethod = methodParseSingleValue.MakeGenericMethod(typeof(T).GetGenericArguments());
                MethodInfo addMethod        = typeof(T).GetMethod("Add");

                // Populate the list
                for (int i = 0; i < count; i++)
                {
                    string strVal = configNode.GetValue(key, i);
                    try
                    {
                        addMethod.Invoke(list, new object[] { parseValueMethod.Invoke(null, new object[] { key, strVal, allowExpression }) });
                    }
                    catch (TargetInvocationException tie)
                    {
                        Exception e = ExceptionUtil.UnwrapTargetInvokationException(tie);
                        if (e != null)
                        {
                            throw e;
                        }
                        throw;
                    }
                }

                return(list);
            }
            else if (typeof(T).Name == "Nullable`1")
            {
                // Create the generic method
                MethodInfo parseValueMethod = typeof(ConfigNodeUtil).GetMethod("ParseValue",
                                                                               BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(ConfigNode), typeof(string), typeof(bool) }, null);
                parseValueMethod = parseValueMethod.MakeGenericMethod(typeof(T).GetGenericArguments());

                // Call it
                try
                {
                    return((T)parseValueMethod.Invoke(null, new object[] { configNode, key, allowExpression }));
                }
                catch (TargetInvocationException tie)
                {
                    Exception e = ExceptionUtil.UnwrapTargetInvokationException(tie);
                    if (e != null)
                    {
                        throw e;
                    }
                    throw;
                }
            }

            // Get string value, pass to parse single value function
            string stringValue = configNode.GetValue(key);

            return(ParseSingleValue <T>(key, stringValue, allowExpression));
        }
Example #27
0
        public bool Initialize(ContractType contractType)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;
            try
            {
                this.contractType = contractType;
                if (contractType.trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                }

                LoggingUtil.LogDebug(this, "Initializing contract: " + contractType);

                // Set stuff from contract type
                subType    = contractType.name;
                hash       = contractType.hash;
                AutoAccept = contractType.autoAccept;

                // Set the contract expiry
                if (contractType.maxExpiry == 0.0f)
                {
                    LoggingUtil.LogDebug(this, contractType.name + ": Setting expirty to none");
                    SetExpiry();
                    expiryType = DeadlineType.None;
                }
                else
                {
                    SetExpiry(contractType.minExpiry, contractType.maxExpiry);
                    // Force set the expiry, in stock this is normally done on Contract.Offer()
                    dateExpire = GameTime + TimeExpiry;
                }

                // Set the contract deadline
                if (contractType.deadline == 0.0f)
                {
                    deadlineType = Contract.DeadlineType.None;
                }
                else
                {
                    SetDeadlineDays(contractType.deadline, null);
                }

                // Set rewards
                SetScience(contractType.rewardScience, contractType.targetBody);
                SetReputation(contractType.rewardReputation, contractType.failureReputation, contractType.targetBody);
                SetFunds(contractType.advanceFunds, contractType.rewardFunds, contractType.advanceFunds + contractType.failureFunds, contractType.targetBody);

                // Copy text from contract type
                title            = contractType.title;
                synopsis         = contractType.synopsis;
                completedMessage = contractType.completedMessage;
                notes            = contractType.notes;

                // Set the agent
                if (contractType.agent != null)
                {
                    agent = contractType.agent;
                }
                else
                {
                    agent = AgentList.Instance.GetSuitableAgentForContract(this);
                }

                // Set description
                if (string.IsNullOrEmpty(contractType.description) && agent != null)
                {
                    // Generate the contract description
                    description = TextGen.GenerateBackStories("ConfiguredContract", agent.Name, contractType.topic, contractType.subject, random.Next(), true, true, true);
                }
                else
                {
                    description = contractType.description;
                }

                // Generate behaviours
                behaviours = new List <ContractBehaviour>();
                if (!contractType.GenerateBehaviours(this))
                {
                    return(false);
                }

                // Generate parameters
                bool paramsGenerated = contractType.GenerateParameters(this);
                bodiesLoaded = false;
                contractType.contractBodies = ContractBodies;
                if (!paramsGenerated)
                {
                    return(false);
                }

                // Do a very late research bodies check
                try
                {
                    contractType.ResearchBodiesCheck(this);
                }
                catch (ContractRequirementException)
                {
                    return(false);
                }

                // Copy in the requirement nodes
                requirements = new List <ContractRequirement>();
                foreach (ContractRequirement requirement in contractType.Requirements)
                {
                    requirements.Add(requirement);
                }

                LoggingUtil.LogDebug(this, "Initialized contract: " + contractType);
                return(true);
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error initializing contract " + contractType);
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_GENERATION, e,
                                                         contractType == null ? "unknown" : contractType.FullName);

                return(false);
            }
            finally
            {
                LoggingUtil.logLevel = origLogLevel;
            }
        }
Example #28
0
        protected override void OnLoad(ConfigNode node)
        {
            try
            {
                subType          = node.GetValue("subtype");
                contractType     = ContractType.GetContractType(subType);
                title            = ConfigNodeUtil.ParseValue <string>(node, "title", contractType != null ? contractType.title : subType);
                description      = ConfigNodeUtil.ParseValue <string>(node, "description", contractType != null ? contractType.description : "");
                synopsis         = ConfigNodeUtil.ParseValue <string>(node, "synopsis", contractType != null ? contractType.synopsis : "");
                completedMessage = ConfigNodeUtil.ParseValue <string>(node, "completedMessage", contractType != null ? contractType.completedMessage : "");
                notes            = ConfigNodeUtil.ParseValue <string>(node, "notes", contractType != null ? contractType.notes : "");
                hash             = ConfigNodeUtil.ParseValue <int>(node, "hash", contractType != null ? contractType.hash : 0);
                targetBody       = ConfigNodeUtil.ParseValue <CelestialBody>(node, "targetBody", null);

                // Load the unique data
                ConfigNode dataNode = node.GetNode("UNIQUE_DATA");
                if (dataNode != null)
                {
                    // Handle individual values
                    foreach (ConfigNode.Value pair in dataNode.values)
                    {
                        string typeName = pair.value.Remove(pair.value.IndexOf(":"));
                        string value    = pair.value.Substring(typeName.Length + 1);
                        Type   type     = ConfigNodeUtil.ParseTypeValue(typeName);

                        // Prevents issues with vessels not getting loaded in some scenes (ie. VAB)
                        if (type == typeof(Vessel))
                        {
                            type = typeof(Guid);
                        }

                        if (type == typeof(string))
                        {
                            uniqueData[pair.name] = value;
                        }
                        else
                        {
                            // Get the ParseValue method
                            MethodInfo parseValueMethod = typeof(ConfigNodeUtil).GetMethods().Where(m => m.Name == "ParseSingleValue").Single();
                            parseValueMethod = parseValueMethod.MakeGenericMethod(new Type[] { type });

                            // Invoke the ParseValue method
                            uniqueData[pair.name] = parseValueMethod.Invoke(null, new object[] { pair.name, value, false });
                        }
                    }
                }

                foreach (ConfigNode child in node.GetNodes("BEHAVIOUR"))
                {
                    ContractBehaviour behaviour = ContractBehaviour.LoadBehaviour(child, this);
                    behaviours.Add(behaviour);
                }

                foreach (ConfigNode child in node.GetNodes("REQUIREMENT"))
                {
                    ContractRequirement requirement = ContractRequirement.LoadRequirement(child);
                    requirements.Add(requirement);
                }

                // If the contract type is null, then it likely means that it was uninstalled
                if (contractType == null)
                {
                    LoggingUtil.LogWarning(this, "Error loading contract for contract type '" + subType +
                                           "'.  The contract type either failed to load or was uninstalled.");
                    try
                    {
                        if (ContractState == State.Active || ContractState == State.Offered)
                        {
                            SetState(ContractState == State.Active ? State.Failed : State.Withdrawn);
                        }
                    }
                    catch { }
                    return;
                }

                OnContractLoaded.Fire(this);
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading contract from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_LOAD, e, this);

                try
                {
                    SetState(State.Failed);
                }
                catch { }
            }
        }
Example #29
0
        protected override void OnSave(ConfigNode node)
        {
            try
            {
                node.SetValue("type", "ConfiguredContract");

                node.AddValue("subtype", subType);
                if (!string.IsNullOrEmpty(title))
                {
                    node.AddValue("title", title.Replace("\n", "&br;"));
                }
                if (!string.IsNullOrEmpty(description))
                {
                    node.AddValue("description", description.Replace("\n", "&br;"));
                }
                if (!string.IsNullOrEmpty(synopsis))
                {
                    node.AddValue("synopsis", synopsis.Replace("\n", "&br;"));
                }
                if (!string.IsNullOrEmpty(completedMessage))
                {
                    node.AddValue("completedMessage", completedMessage.Replace("\n", "&br;"));
                }
                if (!string.IsNullOrEmpty(notes))
                {
                    node.AddValue("notes", notes.Replace("\n", "&br;"));
                }
                node.AddValue("hash", hash);

                if (targetBody != null)
                {
                    node.AddValue("targetBody", targetBody.name);
                }

                // Store the unique data
                if (uniqueData.Any())
                {
                    ConfigNode dataNode = new ConfigNode("UNIQUE_DATA");
                    node.AddNode(dataNode);
                    foreach (KeyValuePair <string, object> p in uniqueData.Where(p => p.Value != null))
                    {
                        PersistentDataStore.StoreToConfigNode(dataNode, p.Key, p.Value);
                    }
                }

                foreach (ContractBehaviour behaviour in behaviours)
                {
                    ConfigNode child = new ConfigNode("BEHAVIOUR");
                    behaviour.Save(child);
                    node.AddNode(child);
                }

                // Store requirements
                if (requirements == null)
                {
                    requirements = new List <ContractRequirement>();
                    if (contractType != null)
                    {
                        foreach (ContractRequirement requirement in contractType.Requirements)
                        {
                            requirements.Add(requirement);
                        }
                    }
                }

                foreach (ContractRequirement requirement in requirements)
                {
                    ConfigNode child = new ConfigNode("REQUIREMENT");
                    if (child.nodes.Count > 0)
                    {
                        requirement.Save(child);
                        node.AddNode(child);
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error saving contract '" + subType + "' to persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_SAVE, e, this);

                SetState(State.Failed);
            }
        }
Example #30
0
        /// <summary>
        /// Loads the contract type details from the given config node.
        /// </summary>
        /// <param name="configNode">The config node to load from.</param>
        /// <returns>Whether the load was successful.</returns>
        public bool Load(ConfigNode configNode)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;

            try
            {
                // Logging on
                LoggingUtil.CaptureLog = true;
                ConfigNodeUtil.SetCurrentDataNode(null);
                LoggingUtil.LogInfo(this, "Loading CONTRACT_TYPE: '" + name + "'");

                // Clear the config node cache
                ConfigNodeUtil.ClearCache(true);

                // Load values that are immediately required
                bool valid = true;
                valid &= ConfigNodeUtil.ParseValue <ContractGroup>(configNode, "group", x => group = x, this, (ContractGroup)null);

                // Set up the data node
                dataNode = new DataNode(configNode.GetValue("name"), group != null ? group.dataNode : null, this);
                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "name", x => name = x, this);

                // Try to turn on trace mode
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "trace", x => trace = x, this, false);
                if (trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                    LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name);
                }

                // Load contract text details
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "title", x => title = x, this);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "tag", x => tag = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "description", x => description = x, this, (string)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "topic", x => topic = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "subject", x => subject = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "notes", x => notes = x, this, (string)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "synopsis", x => synopsis = x, this);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "completedMessage", x => completedMessage = x, this);

                if (configNode.HasValue("motivation)"))
                {
                    string motivation;
                    valid &= ConfigNodeUtil.ParseValue <string>(configNode, "motivation", x => motivation = x, this, "");
                    LoggingUtil.LogWarning(this, "The 'motivation' attribute is no longer supported as of Contract Configurator 1.23.0");
                }

                // Load optional attributes
                valid &= ConfigNodeUtil.ParseValue <Agent>(configNode, "agent", x => agent = x, this, group != null ? group.agent : null);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "minExpiry", x => minExpiry = x, this, 5.0f, x => Validation.GE(x, 0.0f));
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "maxExpiry", x => maxExpiry = x, this, 100.0f, x => Validation.GE(x, minExpiry));
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "deadline", x => deadline = x, this, 0.0f, x => Validation.GE(x, 0.0f));
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "cancellable", x => cancellable = x, this, true);
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "declinable", x => declinable = x, this, true);
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "autoAccept", x => autoAccept = x, this, false);
                valid &= ConfigNodeUtil.ParseValue <List <Contract.ContractPrestige> >(configNode, "prestige", x => prestige = x, this, new List <Contract.ContractPrestige>());
                valid &= ConfigNodeUtil.ParseValue <CelestialBody>(configNode, "targetBody", x => targetBody = x, this, (CelestialBody)null);

                valid &= ConfigNodeUtil.ParseValue <int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0));
                valid &= ConfigNodeUtil.ParseValue <int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, (maxCompletions == 0 ? 4 : 0), x => Validation.GE(x, 0));

                // Load rewards
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardFunds", x => rewardFunds = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardReputation", x => rewardReputation = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardScience", x => rewardScience = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "failureFunds", x => failureFunds = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "failureReputation", x => failureReputation = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "advanceFunds", x => advanceFunds = x, this, 0.0f);

                // Load other values
                if (configNode.HasValue("weight"))
                {
                    double weight;
                    valid &= ConfigNodeUtil.ParseValue <double>(configNode, "weight", x => weight = x, this);
                    LoggingUtil.LogWarning(this, ErrorPrefix() + ": The weight attribute is deprecated as of Contract Configurator 1.15.0.  Contracts are no longer generated using a weighted system.");
                }

                // Merge in data from the parent contract group
                for (ContractGroup currentGroup = group; currentGroup != null; currentGroup = currentGroup.parent)
                {
                    // Merge dataValues - this is a flag saying what values need to be unique at the contract level
                    foreach (KeyValuePair <string, DataValueInfo> pair in currentGroup.dataValues)
                    {
                        dataValues[currentGroup.name + ":" + pair.Key] = pair.Value;
                    }

                    // Merge uniquenessChecks
                    foreach (KeyValuePair <string, DataNode.UniquenessCheck> pair in currentGroup.uniquenessChecks)
                    {
                        uniquenessChecks[currentGroup.name + ":" + pair.Key] = pair.Value;
                    }
                }

                // Load DATA nodes
                valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks);

                log = LoggingUtil.capturedLog;
                LoggingUtil.CaptureLog = false;

                // Load parameters
                foreach (ConfigNode contractParameter in ConfigNodeUtil.GetChildNodes(configNode, "PARAMETER"))
                {
                    ParameterFactory paramFactory = null;
                    valid &= ParameterFactory.GenerateParameterFactory(contractParameter, this, out paramFactory);
                    if (paramFactory != null)
                    {
                        paramFactories.Add(paramFactory);
                        if (paramFactory.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Load behaviours
                foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "BEHAVIOUR"))
                {
                    BehaviourFactory behaviourFactory = null;
                    valid &= BehaviourFactory.GenerateBehaviourFactory(requirementNode, this, out behaviourFactory);
                    if (behaviourFactory != null)
                    {
                        behaviourFactories.Add(behaviourFactory);
                        if (behaviourFactory.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Load requirements
                foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT"))
                {
                    ContractRequirement requirement = null;
                    valid &= ContractRequirement.GenerateRequirement(requirementNode, this, out requirement);
                    if (requirement != null)
                    {
                        requirements.Add(requirement);
                        if (requirement.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Logging on
                LoggingUtil.CaptureLog = true;

                // Check we have at least one valid parameter
                if (paramFactories.Count() == 0)
                {
                    LoggingUtil.LogError(this, ErrorPrefix() + ": Need at least one parameter for a contract!");
                    valid = false;
                }

                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                //
                // Process the DATA_EXPAND nodes - this could cause a restart to the load process
                //
                ConfigNode dataExpandNode = configNode.GetNodes("DATA_EXPAND").FirstOrDefault();
                if (dataExpandNode != null)
                {
                    Type type = null;
                    valid &= ConfigNodeUtil.ParseValue <Type>(dataExpandNode, "type", x => type = x, this);

                    if (type != null)
                    {
                        foreach (ConfigNode.Value pair in dataExpandNode.values)
                        {
                            string key = pair.name;
                            if (key != "type")
                            {
                                object value = null;

                                // Create the setter function
                                Type     actionType = typeof(Action <>).MakeGenericType(type);
                                Delegate del        = Delegate.CreateDelegate(actionType, value, typeof(DataNode).GetMethod("NullAction"));

                                // Set the ParseDataExpandString method generic value
                                MethodInfo method = methodParseExpand.MakeGenericMethod(new Type[] { type });

                                // Invoke the ParseDataExpandString method
                                List <string> values = (List <string>)method.Invoke(this, new object[] { dataExpandNode, key });

                                // Stop at this point if we're invalid
                                if (values == null || !valid)
                                {
                                    if (values == null)
                                    {
                                        LoggingUtil.LogWarning(this, ErrorPrefix() + ": Received an empty list of values when trying to do a DATA_EXPAND");
                                    }
                                    valid = false;
                                    break;
                                }

                                // Expand
                                configNode.RemoveNode(dataExpandNode);
                                foreach (string val in values)
                                {
                                    // Set up for expansion
                                    ConfigNode copy    = configNode.CreateCopy();
                                    string     newName = name + "." + val;
                                    copy.SetValue("name", newName);

                                    // Set up the data node in the copy
                                    ConfigNode dataNode = new ConfigNode("DATA");
                                    copy.AddNode(dataNode);
                                    dataNode.AddValue("type", dataExpandNode.GetValue("type"));
                                    dataNode.AddValue(key, val);

                                    ContractType contractTypeCopy = new ContractType(newName);
                                    contractTypeCopy.Load(copy);
                                }

                                // Remove the original
                                contractTypes.Remove(name);

                                // Don't do any more loading for this one
                                LoggingUtil.LogInfo(this, "Successfully expanded CONTRACT_TYPE '" + name + "'");
                                return(valid);
                            }
                        }
                    }
                }

                //
                // Do the deferred loads
                //
                valid &= ConfigNodeUtil.ExecuteDeferredLoads();

                //
                // Do generic fields that need to happen after deferred loads
                //
                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                // Generic title
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "genericTitle", x => genericTitle = x, this, title);
                if (!configNode.HasValue("genericTitle") && !dataNode.IsDeterministic("title"))
                {
                    LoggingUtil.Log(minVersion >= ContractConfigurator.ENHANCED_UI_VERSION ? LoggingUtil.LogLevel.ERROR : LoggingUtil.LogLevel.WARNING, this,
                                    ErrorPrefix() + ": The field 'genericTitle' is required when the title is not determistic (ie. when expressions are used).");

                    // Error on newer versions of contract packs
                    if (minVersion >= ContractConfigurator.ENHANCED_UI_VERSION)
                    {
                        valid = false;
                    }
                }
                else if (!dataNode.IsDeterministic("genericTitle"))
                {
                    valid = false;
                    LoggingUtil.LogError(this, ErrorPrefix() + ": The field 'genericTitle' must be deterministic.");
                }

                // Generic description
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "genericDescription", x => genericDescription = x, this, description);
                if (!configNode.HasValue("genericDescription") && !dataNode.IsDeterministic("description"))
                {
                    LoggingUtil.Log(minVersion >= ContractConfigurator.ENHANCED_UI_VERSION ? LoggingUtil.LogLevel.ERROR : LoggingUtil.LogLevel.WARNING, this,
                                    ErrorPrefix() + ": The field 'genericDescription' is required when the description is not determistic (ie. when expressions are used).");

                    // Error on newer versions of contract packs
                    if (minVersion >= ContractConfigurator.ENHANCED_UI_VERSION)
                    {
                        valid = false;
                    }
                }
                else if (!dataNode.IsDeterministic("genericDescription"))
                {
                    valid = false;
                    LoggingUtil.LogError(this, ErrorPrefix() + ": The field 'genericDescription' must be deterministic.");
                }

                // Sorting key
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "sortKey", x => sortKey = x, this, genericTitle);

                // Check for unexpected values - always do this last
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this);

                if (valid)
                {
                    LoggingUtil.LogInfo(this, "Successfully loaded CONTRACT_TYPE '" + name + "'");
                }
                else
                {
                    LoggingUtil.LogWarning(this, "Errors encountered while trying to load CONTRACT_TYPE '" + name + "'");
                }
                config  = configNode.ToString();
                hash    = config.GetHashCode();
                enabled = valid;
                log    += LoggingUtil.capturedLog;

                if (LoggingUtil.logLevel >= LoggingUtil.LogLevel.DEBUG)
                {
                    // Get the contract configurator log file
                    string[] dirComponents  = new string[] { KSPUtil.ApplicationRootPath, "GameData", "ContractConfigurator", "log", (group == null ? "!NO_GROUP" : group.Root.name) };
                    string[] pathComponents = dirComponents.Union(new string[] { name + ".log" }).ToArray();
                    string   dir            = string.Join(Path.DirectorySeparatorChar.ToString(), dirComponents);
                    string   path           = string.Join(Path.DirectorySeparatorChar.ToString(), pathComponents);

                    // Delete the file if it exists
                    if (File.Exists(path))
                    {
                        try
                        {
                            File.Delete(path);
                        }
                        catch (Exception e)
                        {
                            LoggingUtil.LogException(new Exception("Exception while attempting to delete the file: " + path, e));
                        }
                    }

                    // Create the directory if it doesn't exist
                    Directory.CreateDirectory(dir);

                    // Now write the config and the cleaned up log to it
                    try
                    {
                        using (StreamWriter sw = File.AppendText(path))
                        {
                            sw.Write("Debug information for CONTRACT_TYPE '" + name + "':\n");
                            sw.Write("\nConfiguration:\n");
                            sw.Write(config);
                            sw.Write("\nData Nodes:\n");
                            sw.Write(DataNodeDebug(dataNode));
                            sw.Write("\nOutput log:\n");
                            sw.Write(log);
                        }
                    }
                    catch
                    {
                        LoggingUtil.LogError(this, "Exception while attempting to write to the file: " + path);
                    }
                }

                return(valid);
            }
            catch (Exception e)
            {
                enabled = false;
                throw new Exception("Error loading CONTRACT_TYPE '" + name + "'", e);
            }
            finally
            {
                LoggingUtil.CaptureLog = false;
                LoggingUtil.logLevel   = origLogLevel;
                loaded = true;
            }
        }