public override bool MeetRequirements()
        {
            // ContractType already chosen, check if still meets requirements.
            if (contractType != null)
            {
                bool meets = contractType.MeetRequirements(this, contractType);
                if (ContractState == State.Offered && !meets)
                {
                    LoggingUtil.LogWarning(this, "Cancelled contract '" + title + "', as it no longer meets the requirements.");
                }
                if (ContractState == State.Active && !meets)
                {
                    LoggingUtil.LogWarning(this, "Removed contract '" + title + "', as it no longer meets the requirements.");
                }
                return(meets);
            }
            else if (ContractState == State.Withdrawn)
            {
                // Special case for pre-loader
                return(true);
            }

            // No ContractType chosen
            return(false);
        }
Beispiel #2
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");
            }
        }
Beispiel #3
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>
        /// Validates that the given config node does NOT contain the given value.
        /// </summary>
        /// <param name="configNode">The ConfigNode to check.</param>
        /// <param name="field">The field to exclude</param>
        /// <param name="obj">IContractConfiguratorFactory object for error reporting</param>
        /// <returns>Always true, but logs a warning for an unexpected value.</returns>
        public static bool ValidateExcludedValue(ConfigNode configNode, string field, IContractConfiguratorFactory obj)
        {
            if (configNode.HasNode(field) || configNode.HasValue(field))
            {
                LoggingUtil.LogWarning(obj.GetType(), "{0}: unexpected entry '{1}' found, ignored.", obj.ErrorPrefix(), field);
            }

            return(true);
        }
        public override bool Load(ConfigNode configNode)
        {
            // Load base class
            bool valid = base.Load(configNode);

            valid &= ValidateTargetBody(configNode);
            LoggingUtil.LogWarning(this, "EnterSOI is obsolete as of Contract Configurator 0.7.5 and will be removed in 1.0.0.  Please use Orbit or ReachState instead.");

            return(valid);
        }
        public override bool Load(ConfigNode configNode)
        {
            // Load base class
            bool valid = base.Load(configNode);

            valid &= ConfigNodeUtil.ParseValue <FlightLog.EntryType>(configNode, "situation", x => situation = x, this);
            valid &= ValidateTargetBody(configNode);

            LoggingUtil.LogWarning(this, "VesselHasVisited is obsolete as of Contract Configurator 0.7.5 and will be removed in 1.0.0.  Please use Orbit or ReachState (with disableOnStateChange = true) instead.");

            return(valid);
        }
Beispiel #7
0
        /// <summary>
        /// Disables standard contract types as requested by contract packs.
        /// </summary>
        /// <returns>True if the disabling is done.</returns>
        public static bool DisableContracts()
        {
            if (contractsDisabled)
            {
                return(true);
            }

            // Don't do anything if the contract system has not yet loaded
            if (ContractSystem.ContractTypes == null)
            {
                return(false);
            }

            LoggingUtil.LogDebug(typeof(ContractDisabler), "Disabling contract types...");
            ConfigNode[] nodes = GameDatabase.Instance.GetConfigNodes("CONTRACT_CONFIGURATOR");

            int disabledCounter = 0;

            // Start disabling via legacy method
            Dictionary <string, Type> contractsToDisable = new Dictionary <string, Type>();

            foreach (ConfigNode node in nodes)
            {
                foreach (string contractType in node.GetValues("disabledContractType"))
                {
                    LoggingUtil.LogWarning(typeof(ContractDisabler), "Disabling contract " + contractType +
                                           " via legacy method.  Recommend using the disableContractType attribute of the CONTRACT_GROUP node instead.");

                    if (SetContractToDisabled(contractType, null))
                    {
                        disabledCounter++;
                    }
                }
            }

            // Disable via new method
            foreach (ContractGroup contractGroup in ContractGroup.AllGroups.Where(g => g != null && g.parent == null))
            {
                foreach (string contractType in contractGroup.disabledContractType)
                {
                    if (SetContractToDisabled(contractType, contractGroup))
                    {
                        disabledCounter++;
                    }
                }
            }

            LoggingUtil.LogInfo(typeof(ContractDisabler), "Disabled " + disabledCounter + " ContractTypes.");

            contractsDisabled = true;
            return(true);
        }
Beispiel #8
0
        public override bool RequirementMet(ConfiguredContract contract)
        {
            // Cache the tech tree
            if (techTree == null)
            {
                ConfigNode techTreeRoot = ConfigNode.Load(HighLogic.CurrentGame.Parameters.Career.TechTreeUrl);
                if (techTreeRoot != null)
                {
                    techTree = techTreeRoot.GetNode("TechTree");
                }

                if (techTreeRoot == null || techTree == null)
                {
                    LoggingUtil.LogError(this, "Couldn't load tech tree from " + HighLogic.CurrentGame.Parameters.Career.TechTreeUrl);
                    return(false);
                }
            }

            foreach (string tech in techs)
            {
                ConfigNode techNode = techTree.GetNodes("RDNode").Where(n => n.GetValue("id") == tech).FirstOrDefault();

                if (techNode == null)
                {
                    LoggingUtil.LogWarning(this, "No tech node found with id '" + tech + "'");
                    return(false);
                }

                // Get the state of the parents, as well as the anyToUnlock flag
                bool anyToUnlock = ConfigNodeUtil.ParseValue <bool>(techNode, "anyToUnlock");
                IEnumerable <bool> parentsUnlocked = techNode.GetNodes("Parent").
                                                     Select(n => ResearchAndDevelopment.Instance.GetTechState(n.GetValue("parentID"))).
                                                     Select(p => p != null && p.state == RDTech.State.Available);

                // Check if the parents have met the unlock criteria
                if (anyToUnlock && parentsUnlocked.Any(unlocked => unlocked) ||
                    !anyToUnlock && parentsUnlocked.All(unlocked => unlocked))
                {
                    continue;
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// Method for generating ContractParameter objects.  This will call the Generate() method
        /// on the sub-class, load all common parameters and load child parameters.
        /// </summary>
        /// <param name="contract">Contract to generate for</param>
        /// <param name="contractParamHost">Parent object for the ContractParameter</param>
        /// <returns>Generated ContractParameter</returns>
        public virtual ContractParameter Generate(ConfiguredContract contract, IContractParameterHost contractParamHost)
        {
            // First check any requirements
            if (!ContractRequirement.RequirementsMet(contract, contract.contractType, requirements))
            {
                LoggingUtil.LogVerbose(typeof(ParameterFactory), "Returning null for " + contract.contractType.name + "." + name + ": requirements not met.");
                return(null);
            }

            // Generate a parameter using the sub-class logic
            ContractParameter parameter = Generate(contract);

            if (parameter == null)
            {
                LoggingUtil.LogWarning(this, GetType().FullName + ".Generate() returned a null ContractParameter!");
                return(null);
            }

            // Add ContractParameter to the host
            contractParamHost.AddParameter(parameter);

            // Set the funds/science/reputation parameters
            parameter.SetFunds(rewardFunds, failureFunds, targetBody);
            parameter.SetReputation(rewardReputation, failureReputation, targetBody);
            parameter.SetScience(rewardScience, targetBody);

            // Set other flags
            parameter.Optional = optional;
            if (disableOnStateChange != null)
            {
                parameter.DisableOnStateChange = (bool)disableOnStateChange;
            }
            parameter.ID = name;

            // Special stuff for contract configurator parameters
            ContractConfiguratorParameter ccParam = parameter as ContractConfiguratorParameter;

            if (ccParam != null)
            {
                ccParam.completeInSequence = completeInSequence;
                ccParam.notes            = notes;
                ccParam.completedMessage = completedMessage;
                ccParam.hidden           = hidden;
                ccParam.hideChildren     = hideChildren;
            }

            return(parameter);
        }
        public override bool Load(ConfigNode configNode)
        {
            // Load base class
            bool valid = base.Load(configNode);

            if (configNode.HasValue("vesselKey"))
            {
                LoggingUtil.LogWarning(this, "The 'vesselKey' attribute is obsolete as of Contract Configurator 0.7.5.  It will be removed in 1.0.0 in favour of the vessel attribute.");
                valid &= ConfigNodeUtil.ParseValue <VesselIdentifier>(configNode, "vesselKey", x => vesselKey = x, this);
            }
            else
            {
                valid &= ConfigNodeUtil.ParseValue <VesselIdentifier>(configNode, "vessel", x => vesselKey = x, this);
            }

            return(valid);
        }
Beispiel #11
0
        /// <summary>
        /// Performs validation to check if the given config node has values that were not expected.
        /// </summary>
        /// <param name="configNode">The ConfigNode to check.</param>
        /// <param name="obj">IContractConfiguratorFactory object for error reporting</param>
        /// <returns>Always true, but logs a warning if unexpected keys were found</returns>
        public static bool ValidateUnexpectedValues(ConfigNode configNode, IContractConfiguratorFactory obj)
        {
            bool valid = true;

            if (!keysFound.ContainsKey(configNode))
            {
                obj.hasWarnings = true;
                LoggingUtil.LogWarning(obj.GetType(), obj.ErrorPrefix() +
                                       ": did not attempt to load values for ConfigNode!");
                return(false);
            }

            Dictionary <string, int> found = keysFound[configNode];

            foreach (ConfigNode.Value pair in configNode.values)
            {
                if (!found.ContainsKey(pair.name))
                {
                    obj.hasWarnings = true;
                    LoggingUtil.LogWarning(obj.GetType(), obj.ErrorPrefix() +
                                           ": unexpected attribute '" + pair.name + "' found, ignored.");
                }
            }

            foreach (ConfigNode child in configNode.nodes)
            {
                // Exceptions
                if (child.name == "PARAMETER" && (obj is ContractType || obj is ParameterFactory) ||
                    child.name == "REQUIREMENT" && (obj is ContractType || obj is ParameterFactory || obj is ContractRequirement) ||
                    child.name == "BEHAVIOUR" && (obj is ContractType) ||
                    child.name == "ORBIT" && (obj is Behaviour.OrbitGeneratorFactory || obj is Behaviour.SpawnVesselFactory || obj is Behaviour.SpawnKerbalFactory))
                {
                    continue;
                }

                if (!found.ContainsKey(child.name))
                {
                    obj.hasWarnings = true;
                    LoggingUtil.LogWarning(obj.GetType(), obj.ErrorPrefix() +
                                           ": unexpected child node '" + child.name + "' found, ignored.");
                }
            }


            return(valid);
        }
Beispiel #12
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 { }
            }
        }
Beispiel #13
0
 public override bool MeetRequirements()
 {
     // No ContractType chosen
     if (contractType == null)
     {
         return(SelectContractType());
     }
     else
     {
         // ContractType already chosen, check if still meets requirements.
         bool meets = contractType.MeetRequirements(this);
         if (ContractState == State.Active && !meets)
         {
             LoggingUtil.LogWarning(this, "Removed contract '" + title + "', as it no longer meets the requirements.");
         }
         return(meets);
     }
 }
Beispiel #14
0
        public static void SetContractToDisabled(string contract, ContractGroup group)
        {
            Type contractType = contractTypes.Where(t => t.Name == contract).FirstOrDefault();

            if (contractType == null)
            {
                LoggingUtil.LogWarning(typeof(ContractDisabler), "Couldn't find ContractType '" + contract + "' to disable.");
            }

            if (!contractDetails.ContainsKey(contractType))
            {
                contractDetails[contractType] = new ContractDetails(contractType);
            }
            ContractDetails details = contractDetails[contractType];

            details.disablingGroups.AddUnique(group);
            SetContractState(contractType, false);
        }
Beispiel #15
0
        /// <summary>
        /// Performs validation to check if the given config node has values that were not expected.
        /// </summary>
        /// <param name="configNode">The ConfigNode to check.</param>
        /// <param name="obj">IContractConfiguratorFactory object for error reporting</param>
        /// <returns>Always true, but logs a warning if unexpected keys were found</returns>
        public static bool ValidateUnexpectedValues(ConfigNode configNode, IContractConfiguratorFactory obj)
        {
            if (!keysFound.ContainsKey(configNode))
            {
                LoggingUtil.LogWarning(obj.GetType(), obj.ErrorPrefix() +
                                       ": did not attempt to load values for ConfigNode!");
                return(false);
            }

            Dictionary <string, int> found = keysFound[configNode];

            foreach (ConfigNode.Value pair in configNode.values)
            {
                if (!found.ContainsKey(pair.name))
                {
                    LoggingUtil.LogWarning(obj.GetType(), obj.ErrorPrefix() +
                                           ": unexpected entry '" + pair.name + "' found, ignored.");
                }
            }

            return(true);
        }
Beispiel #16
0
        public static List <Type> GetAllTypes <T>()
        {
            // Get everything that extends ParameterFactory
            List <Type> allTypes = new List <Type>();

            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                try
                {
                    foreach (Type t in from type in assembly.GetTypes() where type.IsSubclassOf(typeof(T)) select type)
                    {
                        allTypes.Add(t);
                    }
                }
                catch (Exception e)
                {
                    LoggingUtil.LogWarning(typeof(ContractConfigurator), "Error loading types from assembly " + assembly.FullName + ": " + e.Message);
                }
            }

            return(allTypes);
        }
        /// <summary>
        /// Verifies that the contract group is not empty.
        /// </summary>
        public void CheckEmpty()
        {
            bool atLeastOne = false;

            foreach (ContractType contractType in ContractType.AllContractTypes.Where(ct => ct.group == this))
            {
                atLeastOne = true;
                break;
            }

            // Need at least one contract in the group
            if (!atLeastOne)
            {
                // Try for a child group
                if (!ContractGroup.AllGroups.Where(g => g != null && g.parent != null && g.parent.name == name).Any())
                {
                    LoggingUtil.CaptureLog = true;
                    LoggingUtil.LogWarning(this, "Contract group '" + name + "' contains no contract types or child groups!");
                    log += LoggingUtil.capturedLog;
                    LoggingUtil.CaptureLog = false;
                    hasWarnings            = true;
                }
            }
        }
        /// <summary>
        /// Generates a new ParameterFactory from the given ConfigNode.
        /// </summary>
        /// <param name="parameterConfig">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this parameter factory falls under</param>
        /// <param name="paramFactory">The ParameterFactory object.</param>
        /// <param name="parent">ParameterFactory to use as the parent</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateParameterFactory(ConfigNode parameterConfig, ContractType contractType, out ParameterFactory paramFactory, ParameterFactory parent = null)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = parameterConfig.GetValue("type");
            string name = parameterConfig.HasValue("name") ? parameterConfig.GetValue("name") : type;

            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "PARAMETER '" + parameterConfig.GetValue("name") + "' does not specify the mandatory 'type' attribute.");
                paramFactory = new InvalidParameterFactory();
                valid        = false;
            }
            else if (!factories.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "PARAMETER '" + parameterConfig.GetValue("name") + "' of type '" + parameterConfig.GetValue("type") + "': " +
                                     "Unknown parameter '" + type + "'.");
                paramFactory = new InvalidParameterFactory();
                valid        = false;
            }
            else
            {
                // Create an instance of the factory
                paramFactory = (ParameterFactory)Activator.CreateInstance(factories[type]);
            }

            // Set attributes
            paramFactory.parent       = parent;
            paramFactory.contractType = contractType;
            paramFactory.dataNode     = new DataNode(name, parent != null ? parent.dataNode : contractType.dataNode, paramFactory);

            // Load child requirements
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(parameterConfig, "REQUIREMENT"))
            {
                ContractRequirement req = null;
                valid &= ContractRequirement.GenerateRequirement(childNode, contractType, out req, paramFactory);
                if (req != null)
                {
                    paramFactory.requirements.Add(req);
                    if (req.hasWarnings)
                    {
                        paramFactory.hasWarnings = true;
                    }
                }
            }

            // Load config
            if (!paramFactory.Load(parameterConfig))
            {
                // If there was a load failure, check if there are requirements
                if (paramFactory.requirements.Count > 0)
                {
                    LoggingUtil.LogWarning(paramFactory, "Ignoring failed parameter with child requirements.");
                }
                else
                {
                    valid = false;
                }
            }

            // Late initialize for iterator keys
            valid &= DataNode.InitializeIteratorKey(parameterConfig, paramFactory);

            // Check for unexpected values - always do this last
            if (paramFactory.GetType() != typeof(InvalidParameterFactory))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(parameterConfig, paramFactory);
            }

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

            // Load child nodes
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(parameterConfig, "PARAMETER"))
            {
                ParameterFactory child = null;
                valid &= ParameterFactory.GenerateParameterFactory(childNode, contractType, out child, paramFactory);
                if (child != null)
                {
                    paramFactory.childNodes.Add(child);
                    if (child.hasWarnings)
                    {
                        paramFactory.hasWarnings = true;
                    }
                }
            }

            paramFactory.enabled = valid;

            return(valid);
        }
Beispiel #19
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)
        {
            try
            {
                // Logging on
                LoggingUtil.CaptureLog = true;

                dataNode = new DataNode(configNode.GetValue("name"), this);

                ConfigNodeUtil.ClearCache(true);
                ConfigNodeUtil.SetCurrentDataNode(dataNode);
                bool valid = true;

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

                // Load contract text details
                valid &= ConfigNodeUtil.ParseValue <ContractGroup>(configNode, "group", x => group = x, this, (ContractGroup)null);
                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, (string)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "subject", x => subject = x, this, (string)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "motivation", x => motivation = x, this, (string)null);
                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);

                // Load optional attributes
                valid &= ConfigNodeUtil.ParseValue <Agent>(configNode, "agent", x => agent = x, this, (Agent)null);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "minExpiry", x => minExpiry = x, this, 1.0f, x => Validation.GE(x, 0.0f));
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "maxExpiry", x => maxExpiry = x, this, 7.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 <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, 0, x => Validation.GE(x, 0));

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

                // Load other values
                valid &= ConfigNodeUtil.ParseValue <double>(configNode, "weight", x => weight = x, this, 1.0, x => Validation.GE(x, 0.0f));

                // TODO - these are to be deprecated
                if (configNode.HasValue("targetBodies"))
                {
                    valid &= ConfigNodeUtil.ParseValue <List <CelestialBody> >(configNode, "targetBodies", x => targetBodies = x, this, new List <CelestialBody>());
                    LoggingUtil.LogWarning(this, "The 'targetBodies' attribute is obsolete as of Contract Configurator 0.7.4.  It will be removed in 1.0.0 in favour of the DATA { } node.");
                }
                if (configNode.HasValue("targetVessel"))
                {
                    valid &= ConfigNodeUtil.ParseValue <Vessel>(configNode, "targetVessel", x => targetVessel = x, this, (Vessel)null);
                    LoggingUtil.LogWarning(this, "The 'targetVessel' attribute is obsolete as of Contract Configurator 0.7.4.  It will be removed in 1.0.0 in favour of the DATA { } node.");
                }
                if (configNode.HasValue("targetVessels"))
                {
                    valid &= ConfigNodeUtil.ParseValue <List <Vessel> >(configNode, "targetVessels", x => targetVessels = x, this, new List <Vessel>());
                    LoggingUtil.LogWarning(this, "The 'targetVessels' attribute is obsolete as of Contract Configurator 0.7.4.  It will be removed in 1.0.0 in favour of the DATA { } node.");
                }
                if (configNode.HasValue("targetKerbal"))
                {
                    valid &= ConfigNodeUtil.ParseValue <Kerbal>(configNode, "targetKerbal", x => targetKerbal = x, this, (Kerbal)null);
                    LoggingUtil.LogWarning(this, "The 'targetKerbal' attribute is obsolete as of Contract Configurator 0.7.4.  It will be removed in 1.0.0 in favour of the DATA { } node.");
                }
                if (configNode.HasValue("targetKerbals"))
                {
                    valid &= ConfigNodeUtil.ParseValue <List <Kerbal> >(configNode, "targetKerbals", x => targetKerbals = x, this, new List <Kerbal>());
                    LoggingUtil.LogWarning(this, "The 'targetKerbals' attribute is obsolete as of Contract Configurator 0.7.4.  It will be removed in 1.0.0 in favour of the DATA { } node.");
                }

                // Load DATA nodes
                foreach (ConfigNode data in ConfigNodeUtil.GetChildNodes(configNode, "DATA"))
                {
                    Type type          = null;
                    bool requiredValue = true;
                    valid &= ConfigNodeUtil.ParseValue <Type>(data, "type", x => type = x, this);
                    valid &= ConfigNodeUtil.ParseValue <bool>(data, "requiredValue", x => requiredValue = x, this, true);

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

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

                                // Get the ParseValue method
                                MethodInfo method = typeof(ConfigNodeUtil).GetMethods(BindingFlags.Static | BindingFlags.Public).
                                                    Where(m => m.Name == "ParseValue" && m.GetParameters().Count() == 4).Single();
                                method = method.MakeGenericMethod(new Type[] { type });

                                // Invoke the ParseValue method
                                valid &= (bool)method.Invoke(null, new object[] { data, name, del, this });

                                dataValues[name] = requiredValue;
                            }
                        }
                    }
                }

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

                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.GetType(), ErrorPrefix() + ": Need at least one parameter for a contract!");
                    valid = false;
                }

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

                config  = configNode.ToString();
                hash    = config.GetHashCode();
                enabled = valid;
                log    += LoggingUtil.capturedLog;
                LoggingUtil.CaptureLog = false;

                return(valid);
            }
            catch
            {
                enabled = false;
                throw;
            }
        }
Beispiel #20
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));
        }
Beispiel #21
0
        /// <summary>
        /// Performs adjustments to the contract type list.  Specifically, disables contract types
        /// as per configuration files and adds addtional ConfiguredContract instances based on the
        /// number on contract types.
        /// </summary>
        /// <returns>Whether the changes took place</returns>
        bool AdjustContractTypes()
        {
            // Don't do anything if the contract system has not yet loaded
            if (ContractSystem.ContractTypes == null)
            {
                return(false);
            }

            LoggingUtil.LogDebug(this.GetType(), "Loading CONTRACT_CONFIGURATOR nodes.");
            ConfigNode[] nodes = GameDatabase.Instance.GetConfigNodes("CONTRACT_CONFIGURATOR");

            // Build a unique list of contract types to disable, in case multiple mods try to
            // disable the same ones.
            Dictionary <string, Type> contractsToDisable = new Dictionary <string, Type>();

            foreach (ConfigNode node in nodes)
            {
                foreach (string contractType in node.GetValues("disabledContractType"))
                {
                    // No type for now
                    contractsToDisable[contractType] = null;
                }
            }

            // Map the string to a type
            foreach (Type subclass in GetAllTypes <Contract>())
            {
                string name = subclass.Name;
                if (contractsToDisable.ContainsKey(name))
                {
                    contractsToDisable[name] = subclass;
                }
            }

            // Start disabling!
            int disabledCounter = 0;

            foreach (KeyValuePair <string, Type> p in contractsToDisable)
            {
                // Didn't find a type
                if (p.Value == null)
                {
                    LoggingUtil.LogWarning(this.GetType(), "Couldn't find ContractType '" + p.Key + "' to disable.");
                }
                else
                {
                    LoggingUtil.LogDebug(this.GetType(), "Disabling ContractType: " + p.Value.FullName + " (" + p.Value.Module + ")");
                    ContractSystem.ContractTypes.Remove(p.Value);
                    disabledCounter++;
                }
            }

            LoggingUtil.LogInfo(this.GetType(), "Disabled " + disabledCounter + " ContractTypes.");

            // Now add the ConfiguredContract type
            int count = (int)(ContractType.AllValidContractTypes.Count() / 3.0 + 0.5);

            for (int i = 0; i < count; i++)
            {
                ContractSystem.ContractTypes.Add(typeof(ConfiguredContract));
            }

            LoggingUtil.LogInfo(this.GetType(), "Finished Adjusting ContractTypes");

            return(true);
        }
 public override ContractParameter Generate(Contract contract)
 {
     LoggingUtil.LogWarning(this, "ReachSpace is obsolete since Contract Configurator 1.7.7, use ReachState instead.");
     return(new ReachSpaceCustom(title));
 }
Beispiel #23
0
 public override ContractParameter Generate(Contract contract)
 {
     LoggingUtil.LogWarning(this, "SequenceNode is obsolete as of Contract Configurator 0.6.7, please use the completeInSequence attribute instead.");
     return(new Parameters.SequenceNode(title));
 }
Beispiel #24
0
        /// <summary>
        /// Checks if the "extended" requirements that change due to expressions.
        /// </summary>
        /// <param name="contract">The contract</param>
        /// <returns>Whether the contract can be offered.</returns>
        public bool MeetExtendedRequirements(ConfiguredContract contract, ContractType contractType)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;
            try
            {
                // Turn tracing on
                if (trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                    LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name);
                }

                // Hash check
                if (contract.ContractState == Contract.State.Offered && contract.hash != hash)
                {
                    throw new ContractRequirementException("Contract definition changed.");
                }

                // Check prestige
                if (prestige.Count > 0 && !prestige.Contains(contract.Prestige))
                {
                    throw new ContractRequirementException("Wrong prestige level.");
                }

                // Do a Research Bodies check, if applicable
                ResearchBodiesCheck(contract);

                // Check special values are not null
                if (contract.contractType == null)
                {
                    foreach (KeyValuePair <string, DataValueInfo> pair in dataValues)
                    {
                        // Only check if it is a required value
                        if (pair.Value.required)
                        {
                            CheckRequiredValue(pair.Key);
                        }
                    }
                }

                if (contract.contractType == null || contract.ContractState == Contract.State.Generated || contract.ContractState == Contract.State.Withdrawn)
                {
                    // Check for unique values against other contracts of the same type
                    foreach (KeyValuePair <string, DataNode.UniquenessCheck> pair in uniquenessChecks.Where(p => contract.uniqueData.ContainsKey(p.Key)))
                    {
                        string key = pair.Key;
                        DataNode.UniquenessCheck uniquenessCheck = pair.Value;

                        LoggingUtil.LogVerbose(this, "Doing unique value check for " + key);

                        // Get the active/offered contract lists
                        IEnumerable <ConfiguredContract> contractList = ConfiguredContract.CurrentContracts.
                                                                        Where(c => c != null && c.contractType != null && c != contract);

                        // Add in finished contracts
                        if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.GROUP_ALL)
                        {
                            contractList = contractList.Union(ContractSystem.Instance.ContractsFinished.OfType <ConfiguredContract>().
                                                              Where(c => c != null && c.contractType != null && c != contract));
                        }

                        // Filter anything that doesn't have our key
                        contractList = contractList.Where(c => c.uniqueData.ContainsKey(key));

                        // Check for contracts of the same type
                        if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ACTIVE)
                        {
                            contractList = contractList.Where(c => c.contractType.name == name);
                        }
                        // Check for a shared group
                        else if (contractType.group != null)
                        {
                            contractList = contractList.Where(c => c.contractType.group != null && c.contractType.group.name == contractType.group.name);
                        }
                        // Shared lack of group
                        else
                        {
                            contractList = contractList.Where(c => c.contractType.group == null);
                        }

                        object val = contract.uniqueData[key];
                        if (val != null)
                        {
                            // Special case for vessels - convert to the Guid
                            Vessel vessel = val as Vessel;
                            if (vessel != null)
                            {
                                val = vessel.id;
                            }

                            foreach (ConfiguredContract otherContract in contractList)
                            {
                                if (val.Equals(otherContract.uniqueData[key]))
                                {
                                    throw new ContractRequirementException("Failed on unique value check for key '" + key + "'.");
                                }
                            }
                        }
                    }
                }

                // Check the captured requirements
                if (!ContractRequirement.RequirementsMet(contract, this, contract.requirements != null ? contract.requirements : requirements))
                {
                    throw new ContractRequirementException("Failed on contract requirement check.");
                }

                return(true);
            }
            catch (ContractRequirementException e)
            {
                LoggingUtil.LogLevel level = contract.ContractState == Contract.State.Active ? LoggingUtil.LogLevel.INFO : contract.contractType != null ? LoggingUtil.LogLevel.DEBUG : LoggingUtil.LogLevel.VERBOSE;
                string prefix = contract.contractType != null ? "Cancelling contract of type " + name + " (" + contract.Title + "): " :
                                "Didn't generate contract of type " + name + ": ";
                LoggingUtil.Log(level, this.GetType(), prefix + e.Message);
                return(false);
            }
            catch
            {
                LoggingUtil.LogError(this, "Exception while attempting to check requirements of contract type " + name);
                throw;
            }
            finally
            {
                LoggingUtil.logLevel = origLogLevel;
                loaded = true;
            }
        }
Beispiel #25
0
        /// <summary>
        /// Checks if the "basic" requirements that shouldn't change due to expressions are met.
        /// </summary>
        /// <param name="contract">The contract</param>
        /// <returns>Whether the contract can be offered.</returns>
        public bool MeetBasicRequirements(ConfiguredContract contract)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;
            try
            {
                // Turn tracing on
                if (trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                    LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name);
                }

                // Check funding
                if (advanceFunds < 0)
                {
                    CurrencyModifierQuery q = new CurrencyModifierQuery(TransactionReasons.ContractAdvance, -advanceFunds, 0.0f, 0.0f);
                    GameEvents.Modifiers.OnCurrencyModifierQuery.Fire(q);
                    float fundsRequired = advanceFunds + q.GetEffectDelta(Currency.Funds);

                    if (!Funding.CanAfford(fundsRequired))
                    {
                        throw new ContractRequirementException("Can't afford contract advance cost.");
                    }
                }

                // Check expiry
                if ((contract.ContractState == Contract.State.Offered || contract.ContractState == Contract.State.Withdrawn) &&
                    Planetarium.fetch != null && contract.DateExpire < Planetarium.fetch.time)
                {
                    throw new ContractRequirementException("Expired contract.");
                }

                // Checks for maxSimultaneous/maxCompletions
                if (maxSimultaneous != 0 || maxCompletions != 0)
                {
                    IEnumerable <ConfiguredContract> contractList = ConfiguredContract.CurrentContracts.
                                                                    Where(c => c.contractType != null && c.contractType.name == name && c != contract);

                    // Check if we're breaching the active limit
                    int activeContracts = contractList.Count();
                    if (maxSimultaneous != 0 && activeContracts >= maxSimultaneous)
                    {
                        throw new ContractRequirementException("Too many active contracts.");
                    }

                    // Check if we're breaching the completed limit
                    if (maxCompletions != 0)
                    {
                        if (ActualCompletions() + activeContracts >= maxCompletions)
                        {
                            throw new ContractRequirementException("Too many completed/active/offered contracts.");
                        }
                    }
                }

                // Check the group values
                if (group != null)
                {
                    CheckContractGroup(contract, group);
                }

                return(true);
            }
            catch (ContractRequirementException e)
            {
                LoggingUtil.LogLevel level = contract.ContractState == Contract.State.Active ? LoggingUtil.LogLevel.INFO : contract.contractType != null ? LoggingUtil.LogLevel.DEBUG : LoggingUtil.LogLevel.VERBOSE;
                string prefix = contract.contractType != null ? "Cancelling contract of type " + name + " (" + contract.Title + "): " :
                                "Didn't generate contract of type " + name + ": ";
                LoggingUtil.Log(level, this.GetType(), prefix + e.Message);
                return(false);
            }
            catch
            {
                LoggingUtil.LogError(this, "Exception while attempting to check requirements of contract type " + name);
                throw;
            }
            finally
            {
                LoggingUtil.logLevel = origLogLevel;
                loaded = true;
            }
        }
Beispiel #26
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;
            }
        }
Beispiel #27
0
        /// <summary>
        /// Loads debugging configurations.
        /// </summary>
        public static void LoadDebuggingConfig()
        {
            Debug.Log("[INFO] ContractConfigurator.LoggingUtil: Loading DebuggingConfig node.");
            // Don't know why .GetConfigNode("CC_DEBUGGING") returns null, using .GetConfigNodes("CC_DEBUGGING") works fine.
            ConfigNode[] debuggingConfigs = GameDatabase.Instance.GetConfigNodes("CC_DEBUGGING");

            if (debuggingConfigs.Length > 0)
            {
                try
                {
                    // Fetch config
                    ConfigNode debuggingConfig = debuggingConfigs[0];

                    // Set LogLevel
                    if (debuggingConfig.HasValue("logLevel"))
                    {
                        LoggingUtil.logLevel = (LoggingUtil.LogLevel)Enum.Parse(typeof(LoggingUtil.LogLevel), debuggingConfig.GetValue("logLevel"));
                        LoggingUtil.LogInfo(typeof(LoggingUtil), "Set LogLevel = " + LoggingUtil.logLevel);
                    }

                    // Fetch specific loglevels for given types
                    foreach (ConfigNode levelExceptionNode in debuggingConfig.GetNodes("ADD_LOGLEVEL_EXCEPTION"))
                    {
                        if (levelExceptionNode.HasValue("type") && levelExceptionNode.HasValue("logLevel"))
                        {
                            // Fetch full type name - just search and find the matching one while
                            // ignoring namespace
                            string typeName = levelExceptionNode.GetValue("type");
                            Type   type     = null;
                            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
                            {
                                try
                                {
                                    foreach (Type t in a.GetTypes())
                                    {
                                        if (t.Name == typeName || t.Name.StartsWith(typeName + '`'))
                                        {
                                            type = t;
                                            break;
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Debug.LogWarning("[WARNING] Error loading types from assembly " + a.FullName + ": " + e.Message);
                                }
                            }

                            if (type != null)
                            {
                                LoggingUtil.LogLevel logLevel = (LoggingUtil.LogLevel)Enum.Parse(typeof(LoggingUtil.LogLevel), levelExceptionNode.GetValue("logLevel"));
                                LoggingUtil.AddSpecificLogLevel(type, logLevel);
                            }
                            else
                            {
                                Debug.LogWarning("[WARNING] ContractConfigurator.LoggingUtil: Couldn't find Type with name: '" + typeName + "'");
                            }
                        }
                        else
                        {
                            Debug.LogWarning("[WARNING] ContractConfigurator.LoggingUtil: Couldn't load specific LogLevel node, type or logLevel not given!");
                        }
                    }

                    LoggingUtil.LogInfo(typeof(LoggingUtil), "DebugingConfig loaded!");
                }
                catch (Exception e)
                {
                    LoggingUtil.ClearSpecificLogLevel();
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.INFO;

                    LoggingUtil.LogWarning(typeof(LoggingUtil), "Debugging Config failed to load! Message: '" + e.Message + "' Set LogLevel to INFO and cleaned specific LogLevels");
                }
            }
            else
            {
                LoggingUtil.logLevel = LoggingUtil.LogLevel.INFO;
                LoggingUtil.LogWarning(typeof(LoggingUtil), "No debugging config found! LogLevel set to INFO");
            }
        }
        void Update()
        {
            // Detect if there are any new messages
            if (MessageSystem.Instance != null)
            {
                // Derive the internal message list
                if (messageList == null)
                {
                    messageList = (List <MessageSystemButton>)messageListField.GetValue(MessageSystem.Instance);
                }

                // Go through new messages
                if (messageList.Count > lastMessageCount)
                {
                    for (int i = (messageList.Count - lastMessageCount); i-- > 0;)
                    {
                        LoggingUtil.LogVerbose(this, "Message list count = {0}, message {3} = {1} + {2}", messageList.Count, messageList[i].message.message, messageList[i].message.messageTitle, i);
                        if (LocalizationUtil.IsLocalizedString(messageList[i].message.message, deployedScienceTag))
                        {
                            // Pull out the parameters
                            IList <string> parameters = LocalizationUtil.UnLocalizeString(messageList[i].message.message, deployedScienceTag);

                            // Identify the subject
                            ScienceSubject subject = null;
                            foreach (ScienceSubject sub in recentScience)
                            {
                                if (sub.title == parameters[0])
                                {
                                    subject = sub;
                                    break;
                                }
                            }

                            // Subject identified
                            if (subject != null)
                            {
                                LoggingUtil.LogVerbose(this, "Subject identified as {0}", subject.id);

                                // Delete the old message
                                MessageSystem.Instance.DiscardMessage(messageList[i].message.button);

                                // Check for an existing summary level message
                                MessageSystem.Message message = MessageSystem.Instance.FindMessages(m => m.messageTitle == deployedScienceMessageTitle).FirstOrDefault();
                                if (message != null)
                                {
                                    message.IsRead = false;
                                    trackedSubjects.Clear();
                                }
                                trackedSubjects.Add(subject);
                                trackedSubjects.Sort((ss1, ss2) => string.Compare(ss1.title, ss2.title));

                                StringBuilder sb = StringBuilderCache.Acquire();
                                sb.Append(string.Format("<b>{0}</b>:\n", deployedScienceMessageTitle));

                                foreach (ScienceSubject s in trackedSubjects)
                                {
                                    sb.Append(string.Format("    {0}: <color=#6DCFF6><sprite=\"CurrencySpriteAsset\" name=\"Science\" tint=1> {1}</color> / <color=#6DCFF6><sprite=\"CurrencySpriteAsset\" name=\"Science\" tint=1> {2}</color>\n",
                                                            s.title, s.science.ToString("F1"), s.scienceCap.ToString("F1")));
                                }

                                if (message != null)
                                {
                                    message.message = sb.ToStringAndRelease();
                                }
                                else
                                {
                                    MessageSystem.Instance.AddMessage(new MessageSystem.Message(deployedScienceMessageTitle, sb.ToStringAndRelease(),
                                                                                                MessageSystemButton.MessageButtonColor.BLUE, MessageSystemButton.ButtonIcons.ALERT));
                                }
                            }
                            else
                            {
                                LoggingUtil.LogWarning(this, "Couldn't identify subject for deployed experiment with title '{0}'", parameters[0]);
                            }
                        }
                    }

                    recentScience.Clear();
                }
                lastMessageCount = messageList.Count;

                // Check for active screen messages
                screenMessagesToRemove.Clear();
                foreach (ScreenMessage message in ScreenMessages.Instance.ActiveMessages)
                {
                    if (LocalizationUtil.IsLocalizedString(message.message, deployedScienceTag))
                    {
                        screenMessagesToRemove.Add(message);
                    }
                }

                // Remove the messages
                foreach (ScreenMessage message in screenMessagesToRemove)
                {
                    ScreenMessages.RemoveMessage(message);
                }
            }
        }
        /// <summary>
        /// Loads the contract group details from the given config node.
        /// </summary>
        /// <param name="configNode">The config node to load from</param>
        /// <returns>Whether we were successful.</returns>
        public bool Load(ConfigNode configNode)
        {
            try
            {
                dataNode = new DataNode(configNode.GetValue("name"), this);

                LoggingUtil.CaptureLog = true;
                ConfigNodeUtil.SetCurrentDataNode(dataNode);
                bool valid = true;

                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "name", x => name = x, this);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "displayName", x => displayName = x, this, name);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "minVersion", x => minVersionStr = x, this, "");
                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, 0, x => Validation.GE(x, 0));
                valid &= ConfigNodeUtil.ParseValue <List <string> >(configNode, "disabledContractType", x => disabledContractType = x, this, new List <string>());
                valid &= ConfigNodeUtil.ParseValue <Agent>(configNode, "agent", x => agent = x, this, (Agent)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "sortKey", x => sortKey = x, this, displayName);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "tip", x => {}, this, "");

                if (configNode.HasValue("sortKey") && parent == null)
                {
                    sortKey = displayName;
                    LoggingUtil.LogWarning(this, ErrorPrefix() + ": Using the sortKey field is only applicable on child CONTRACT_GROUP elements");
                }

                if (!string.IsNullOrEmpty(minVersionStr))
                {
                    if (Util.Version.VerifyAssemblyVersion("ContractConfigurator", minVersionStr) == null)
                    {
                        valid = false;

                        var    ainfoV  = Attribute.GetCustomAttribute(typeof(ExceptionLogWindow).Assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute;
                        string title   = "Contract Configurator " + ainfoV.InformationalVersion + " Message";
                        string message = "The contract group '" + name + "' requires at least Contract Configurator " + minVersionStr +
                                         " to work, and you are running version " + ainfoV.InformationalVersion +
                                         ".  Please upgrade Contract Configurator to use the contracts in this group.";
                        DialogGUIButton dialogOption = new DialogGUIButton("Okay", new Callback(DoNothing), true);
                        PopupDialog.SpawnPopupDialog(new MultiOptionDialog(message, title, UISkinManager.GetSkin("default"), dialogOption), false, UISkinManager.GetSkin("default"));
                    }
                }

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

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

                // Do post-deferred load warnings
                if (agent == null)
                {
                    LoggingUtil.LogWarning(this, ErrorPrefix() + ": Providing the agent field for all CONTRACT_GROUP nodes is highly recommended, as the agent is used to group contracts in Mission Control.");
                }
                if (string.IsNullOrEmpty(minVersionStr) || minVersion < ContractConfigurator.ENHANCED_UI_VERSION)
                {
                    LoggingUtil.LogWarning(this, ErrorPrefix() + ": No minVersion or older minVersion provided.  It is recommended that the minVersion is set to at least 1.15.0 to turn important warnings for deprecated functionality into errors.");
                }
                if (!configNode.HasValue("displayName"))
                {
                    LoggingUtil.LogWarning(this, ErrorPrefix() + ": No display name provided.  A display name is recommended, as it is used in the Mission Control UI.");
                }

                config = configNode.ToString();
                log   += LoggingUtil.capturedLog;
                LoggingUtil.CaptureLog = false;

                // Load child groups
                foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "CONTRACT_GROUP"))
                {
                    ContractGroup child     = null;
                    string        childName = childNode.GetValue("name");
                    try
                    {
                        child = new ContractGroup(childName);
                    }
                    catch (ArgumentException)
                    {
                        LoggingUtil.LogError(this, "Couldn't load CONTRACT_GROUP '" + childName + "' due to a duplicate name.");
                        valid = false;
                        continue;
                    }

                    child.parent          = this;
                    valid                &= child.Load(childNode);
                    child.dataNode.Parent = dataNode;
                    if (child.hasWarnings)
                    {
                        hasWarnings = true;
                    }
                }

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

                // Invalidate children
                if (!valid)
                {
                    Invalidate();
                }

                enabled = valid;
                return(valid);
            }
            catch
            {
                enabled = false;
                throw;
            }
        }
Beispiel #30
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 { }
            }
        }