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); } }
private bool ValidateVesselList(List <VesselIdentifier> vessels) { bool valid = true; if (parent is VesselParameterGroupFactory) { if (vessels.Count > 1) { LoggingUtil.LogError(this, "{0}: When used under a VesselParameterGroup, no more than one vessel may be specified for the Rendezvous parameter.", ErrorPrefix()); valid = false; } } else { if (vessels.Count == 0) { LoggingUtil.LogError(this, "{0}: Need at least one vessel specified for the Rendezvous parameter.", ErrorPrefix()); valid = false; } if (vessels.Count > 2) { LoggingUtil.LogError(this, "{0}: Cannot specify more than two vessels for the Rendezvous parameter.", ErrorPrefix()); valid = false; } } return(valid); }
/* * Generates a new ParameterFactory from the given ConfigNode. */ public static ParameterFactory GenerateParameterFactory(ConfigNode parameterConfig, ContractType contractType) { // Get the type string type = parameterConfig.GetValue("type"); if (!factories.ContainsKey(type)) { LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," + "PARAMETER '" + parameterConfig.GetValue("name") + "' of type '" + parameterConfig.GetValue("type") + "': " + "No ParameterFactory has been registered for type '" + type + "'."); return(null); } // Create an instance of the factory ParameterFactory paramFactory = (ParameterFactory)Activator.CreateInstance(factories[type]); // Set attributes paramFactory.contractType = contractType; // Load config bool valid = paramFactory.Load(parameterConfig); // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(parameterConfig, paramFactory); return(valid ? paramFactory : null); }
/* * Generates a new BehaviourFactory from the given ConfigNode. */ public static BehaviourFactory GenerateBehaviourFactory(ConfigNode behaviourConfig, ContractType contractType) { // Get the type string type = behaviourConfig.GetValue("type"); if (!factories.ContainsKey(type)) { LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," + "BEHAVIOUR '" + behaviourConfig.GetValue("name") + "' of type '" + behaviourConfig.GetValue("type") + "': " + "No BehaviourFactory has been registered for type '" + type + "'."); return(null); } // Create an instance of the factory BehaviourFactory behaviourFactory = (BehaviourFactory)Activator.CreateInstance(factories[type]); // Set attributes behaviourFactory.contractType = contractType; behaviourFactory.targetBody = contractType.targetBody; // Load config bool valid = behaviourFactory.Load(behaviourConfig); // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(behaviourConfig, behaviourFactory); return(valid ? behaviourFactory : null); }
private bool SetValues(string contractType) { bool valid = true; if (ContractType.AllContractTypes.Any(ct => contractType.StartsWith(ct.name))) { ccType = contractType; } else { ccType = null; Type type = null; ContractConfigurator.contractTypeMap.TryGetValue(contractType, out type); if (type == null) { valid = false; LoggingUtil.LogError(this, "contractType '{0}' must either be a Contract sub-class or ContractConfigurator contract type", contractType); } else { contractClass = type; } } return(valid); }
public override bool Load(ConfigNode configNode) { // Load base class bool valid = base.Load(configNode); valid &= ConfigNodeUtil.ParseValue <List <VesselIdentifier> >(configNode, "vessel", x => vessels = x, this, new List <VesselIdentifier>()); valid &= ConfigNodeUtil.ParseValue <double>(configNode, "distance", x => distance = x, this, 2000.0); if (parent is VesselParameterGroupFactory) { if (vessels.Count > 1) { LoggingUtil.LogError(this, ErrorPrefix() + ": When used under a VesselParameterGroup, no more than one vessel may be specified for the Rendezvous parameter."); valid = false; } } else { if (vessels.Count == 0) { LoggingUtil.LogError(this, ErrorPrefix() + ": Need at least one vessel specified for the Rendezvous parameter."); valid = false; } if (vessels.Count > 2) { LoggingUtil.LogError(this, ErrorPrefix() + ": Cannot specify more than two vessels for the Rendezvous parameter."); valid = false; } } return(valid); }
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); } }
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 ContractParameter Generate(Contract contract) { // Get the OrbitGenerator behaviour OrbitGenerator orbitGenerator = ((ConfiguredContract)contract).Behaviours.OfType <OrbitGenerator>().First <OrbitGenerator>(); if (orbitGenerator == null) { LoggingUtil.LogError(this, "Could not find OrbitGenerator BEHAVIOUR to couple with ReachSpecificOrbit PARAMETER."); return(null); } // Get the parameter for that orbit try { SpecificOrbitWrapper s = orbitGenerator.GetOrbitParameter(index); if (deviationWindow != 0.0) { s.deviationWindow = deviationWindow; } return(new VesselParameterDelegator(s)); } catch (Exception e) { LoggingUtil.LogError(this, "Couldn't find orbit in OrbitGenerator with index " + index + ": " + e.Message); return(null); } }
/// <summary> /// Adds a new ParameterFactory to handle PARAMETER nodes with the given type. /// </summary> /// <param name="factoryType">Type of factory to register.</param> /// <param name="typeName">The name of the factory.</param> public static void Register(Type factoryType, string typeName) { LoggingUtil.LogDebug(typeof(ParameterFactory), "Registering parameter factory class " + factoryType.FullName + " for handling PARAMETER nodes with type = " + typeName + "."); // Make sure we can instantiate it (this will also run any static initializers) Activator.CreateInstance(factoryType); // Check for duplicates Type existingType = null; if (factories.TryGetValue(typeName, out existingType)) { // Give priority to non-Contract Configurator types if (existingType.Assembly == typeof(ParameterFactory).Assembly) { factories[typeName] = factoryType; } // If neither are the Contract Configurator type, throw an error else if (factoryType.Assembly != typeof(ParameterFactory).Assembly) { LoggingUtil.LogError(typeof(ParameterFactory), "Cannot register " + factoryType.FullName + "[" + factoryType.Module + "] to handle type " + typeName + ": already handled by " + existingType.FullName + "[" + existingType.Module + "]"); } } else { // Add it to our list factories.Add(typeName, factoryType); } }
public override bool Load(ConfigNode configNode) { // Load base class bool valid = base.Load(configNode); valid &= ConfigNodeUtil.ParseValue <List <VesselIdentifier> >(configNode, "vessel", x => vessels = x, this, new List <VesselIdentifier>()); valid &= ConfigNodeUtil.ParseValue <VesselIdentifier>(configNode, "defineDockedVessel", x => defineDockedVessel = x, this, (VesselIdentifier)null); // Validate using the config node instead of the list as it may undergo deferred loading if (parent is VesselParameterGroupFactory) { if (configNode.GetValues("vessel").Count() > 1) { LoggingUtil.LogError(this, ErrorPrefix() + ": When used under a VesselParameterGroup, no more than one vessel may be specified for the Docking parameter."); valid = false; } } else { if (configNode.GetValues("vessel").Count() == 0) { LoggingUtil.LogError(this, ErrorPrefix() + ": Need at least one vessel specified for the Docking parameter."); valid = false; } if (configNode.GetValues("vessel").Count() > 2) { LoggingUtil.LogError(this, ErrorPrefix() + ": Cannot specify more than two vessels for the Docking parameter."); valid = false; } } return(valid); }
/// <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"); }
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"); } }
/// <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"); }
/// <summary> /// Ensures the given config node has at least one of the given values. /// </summary> /// <param name="configNode"></param> /// <param name="values"></param> /// <param name="obj"></param> /// <returns></returns> public static bool AtLeastOne(ConfigNode configNode, string[] values, IContractConfiguratorFactory obj) { string output = ""; foreach (string value in values) { if (configNode.HasValue(value)) { return(true); } if (value == values.First()) { output = value; } else if (value == values.Last()) { output += " or " + value; } else { output += ", " + value; } } if (values.Count() == 2) { LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": Either " + output + " is required."); } else { LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": One of " + output + " is required."); } return(false); }
public override bool RequirementMet(ConfiguredContract contract) { // Perform another validation of the target body to catch late validation issues due to expressions if (!ValidateTargetBody()) { return(false); } // Validate the CelestialBodySubtree exists CelestialBodySubtree cbProgress = GetCelestialBodySubtree(); if (cbProgress == null) { LoggingUtil.LogError(this, ": ProgressNode for targetBody " + targetBody.bodyName + " not found."); return(false); } if (checkType == CheckType.MANNED) { return(cbProgress.IsReached && cbProgress.IsCompleteManned); } else if (checkType == CheckType.UNMANNED) { return(cbProgress.IsReached && cbProgress.IsCompleteUnmanned); } return(true); }
/* * Generates a ContractRequirement from a configuration node. */ public static ContractRequirement GenerateRequirement(ConfigNode configNode, ContractType contractType) { // Get the type string type = configNode.GetValue("type"); if (!requirementTypes.ContainsKey(type)) { LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," + "REQUIREMENT '" + configNode.GetValue("name") + "' of type '" + configNode.GetValue("type") + "': " + "No ContractRequirement has been registered for type '" + type + "'."); return(null); } // Create an instance of the ContractRequirement ContractRequirement requirement = (ContractRequirement)Activator.CreateInstance(requirementTypes[type]); // Set attributes requirement.contractType = contractType; requirement.targetBody = contractType.targetBody; // Load config bool valid = requirement.Load(configNode); // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, requirement); return(valid ? requirement : null); }
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"); } }
private List <string> ParseDataExpandString <T>(ConfigNode dataExpandNode, string key) { List <T> values = null; bool valid = ConfigNodeUtil.ParseValue <List <T> >(dataExpandNode, key, x => values = x, this); if (!valid || values == null) { return(null); } // Check that we actually got a deterministic value if (!dataNode.IsDeterministic(key)) { LoggingUtil.LogError(this, ErrorPrefix() + ": Values captured in a DATA_EXPAND node must be deterministic (the value needs to be fixed when loaded on game startup."); return(null); } List <string> results = new List <string>(); foreach (T t in values) { Type type; results.Add(PersistentDataStore.OutputValue(t, out type)); } return(results); }
private bool SetValues(string contractType) { bool valid = true; if (ContractType.AllContractTypes.Any(ct => contractType.StartsWith(ct.name))) { ccType = contractType; } else { ccType = null; IEnumerable <Type> classes = ContractConfigurator.GetAllTypes <Contract>().Where(t => t.Name == contractType); if (!classes.Any()) { valid = false; LoggingUtil.LogError(this, "contractType '" + contractType + "' must either be a Contract sub-class or ContractConfigurator contract type"); } else { contractClass = classes.First(); } } return(valid); }
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"); } }
public static void OnFailure(string errorMessage) { LoggingUtil.LogError(typeof(DraftTwitchViewers), "DraftTwitchViewers Error: {0}", errorMessage); // Wait a bit before trying again Instance.routinesRunning--; Instance.nextAttempt = Time.time + failureDelay; }
private static bool SetupTech() { if (HighLogic.CurrentGame == null) { return(false); } // Cache the tech tree if (allTech == null) { ConfigNode techTreeRoot = ConfigNode.Load(HighLogic.CurrentGame.Parameters.Career.TechTreeUrl); ConfigNode techTree = null; if (techTreeRoot != null) { techTree = techTreeRoot.GetNode("TechTree"); } if (techTreeRoot == null || techTree == null) { LoggingUtil.LogError(typeof(Tech), "Couldn't load tech tree from " + HighLogic.CurrentGame.Parameters.Career.TechTreeUrl); return(false); } allTech = new Dictionary <string, Tech>(); foreach (ConfigNode techNode in techTree.GetNodes("RDNode")) { Tech current = new Tech(techNode.GetValue("id")); current.title = ConfigNodeUtil.ParseValue <string>(techNode, "title"); current.description = ConfigNodeUtil.ParseValue <string>(techNode, "description"); current.cost = ConfigNodeUtil.ParseValue <float>(techNode, "cost"); current.anyToUnlock = ConfigNodeUtil.ParseValue <bool>(techNode, "anyToUnlock"); bool hasParent = false; foreach (ConfigNode parentNode in techNode.GetNodes("Parent")) { string parentID = parentNode.GetValue("parentID"); if (allTech.ContainsKey(parentID)) { hasParent = true; allTech[parentID].children.Add(current); current.level = allTech[parentID].level + 1; } } if (!hasParent) { current.level = 0; } allTech[current.techID] = current; } } return(true); }
/// <summary> /// Validates whether the targetBody value has been loaded. /// </summary> /// <param name="configNode">The ConfigNode to validate against</param> /// <returns>True if the targetBody has been loaded, logs an error and returns false otherwise.</returns> protected virtual bool ValidateTargetBody(ConfigNode configNode) { if (targetBody == null && dataNode.IsDeterministic("targetBody") && dataNode.IsInitialized("targetBody")) { LoggingUtil.LogError(this, ErrorPrefix(configNode) + ": targetBody for " + GetType() + " must be specified."); return(false); } return(true); }
/// <summary> /// Validates whether the targetBody value has been loaded. /// </summary> /// <param name="configNode">ConfigNode to check</param> /// <returns>True if the value is loaded, logs and error and returns false otherwise.</returns> protected virtual bool ValidateTargetBody(ConfigNode configNode) { if (targetBody == null) { LoggingUtil.LogError(this, ErrorPrefix(configNode) + ": targetBody for " + GetType() + " must be specified."); return(false); } return(true); }
/// <summary> /// Checks whether the mandatory field exists, and if not logs and error. Returns true /// only if the validation succeeded. /// </summary> /// <param name="configNode">The ConfigNode to check.</param> /// <param name="field">The child that is expected</param> /// <param name="obj">IContractConfiguratorFactory object for error reporting</param> /// <returns>Whether the validation succeeded, additionally logs an error on failure.</returns> public static bool ValidateMandatoryChild(ConfigNode configNode, string field, IContractConfiguratorFactory obj) { if (!configNode.HasNode(field)) { LoggingUtil.LogError(obj.GetType(), "{0}: missing required child node '{1}'.", obj.ErrorPrefix(), field); return(false); } return(true); }
/// <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; }
private bool ValidateSituations(Vessel.Situations situation) { if (situation != Vessel.Situations.ESCAPING && situation != Vessel.Situations.ORBITING && situation != Vessel.Situations.SUB_ORBITAL) { LoggingUtil.LogError(this, "Invalid situation for Orbit parameter: " + situation + ". For non-orbital situations, use ReachState instead."); return(false); } return(true); }
/// <summary> /// Attempts to parse a value from the config node. 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="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, Func <T, bool> validation) { // Check for required value if (!configNode.HasValue(key) && !configNode.HasNode(key)) { LoggingUtil.LogError(obj, obj.ErrorPrefix(configNode) + ": Missing required value '" + key + "'."); return(false); } return(ParseValue <T>(configNode, key, setter, obj, default(T), validation)); }
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"); } }