Пример #1
0
 /// <summary>Reads custom type fields from the part's config.</summary>
 /// <remarks>
 /// <para>
 /// The consumer code must call this method from the <c>OnLoad</c> method to capture the
 /// PartLoader initalization. This method automatically detects the game loading phase, so it's
 /// safe to call it in every <c>OnLoad</c> inovacation.
 /// </para>
 /// </remarks>
 /// <param name="module">The module to load the data for.</param>
 /// <param name="cfgNode">The config node, passed by the game to the module.</param>
 /// <seealso cref="PersistentFieldAttribute"/>
 /// <seealso cref="StdPersistentGroups.PartConfigLoadGroup"/>
 /// <seealso cref="CopyPartConfigFromPrefab"/>
 /// <example>
 /// <code source="Examples/ConfigUtils/ConfigAccessor-Examples.cs" region="ReadPartConfigExample"/>
 /// </example>
 public static void ReadPartConfig(PartModule module, ConfigNode cfgNode)
 {
     if (!PartLoader.Instance.IsReady())
     {
         ConfigAccessor.ReadFieldsFromNode(
             cfgNode, module.GetType(), module, group: StdPersistentGroups.PartConfigLoadGroup);
     }
 }
Пример #2
0
        /// <summary>Makes pacth from a config node.</summary>
        /// <remarks>
        /// The critical settings will be checked for the sane values. If a bad value found, then the
        /// menthod will throw.
        /// </remarks>
        /// <param name="node">The node to create from.</param>
        /// <param name="context">
        /// The context of node loading. It can be any object, e.g. <c>UrlDir.UrlConfig</c> or
        /// <c>ConfigNode</c>. It's only used for logging errors to give a context for debugging.
        /// </param>
        /// <param name="url">The URL to the node in the game's DB.</param>
        /// <returns>The patch. It's never <c>null.</c></returns>
        static ConfigNodePatch MakeFromNodeInternal(ConfigNode node, object context, string url = null)
        {
            var patchNode = new ConfigNodePatch();

            if (url != null)
            {
                patchNode.sourceConfigUrl = url;
            }
            ConfigAccessor.ReadFieldsFromNode(node, patchNode.GetType(), patchNode);

            // Sanity check of the test rules.
            Preconditions.ConfValueExists(patchNode.name, "node/name", context: context);
            Preconditions.ConfValueExists(patchNode.testSection, "node/TEST", context: context);
            Preconditions.ConfValueExists(
                patchNode.testSection.partTests, "node/TEST/PART", context: context);
            Preconditions.ConfValueExists(
                patchNode.testSection.partTests.GetValue("name"), "node/TEST/PART/name", context: context);
            foreach (var moduleNode in patchNode.testSection.moduleTests)
            {
                Preconditions.ConfValueExists(
                    moduleNode.GetValue("name"), "node/TEST/MODULE/name", context: context);
            }

            // Sanity check of the upgrade rules
            Preconditions.ConfValueExists(patchNode.upgradeSection, "node/UPGRADE", context: context);
            Preconditions.ConfValueExists(
                patchNode.upgradeSection.partRules, "node/UPGRADE/PART", context: context);
            Preconditions.OneOf(patchNode.upgradeSection.partRules.action,
                                new[] { PatchAction.Drop, PatchAction.Fix },
                                "node/UPGRADE/PART/action", context: context);
            foreach (var moduleRule in patchNode.upgradeSection.moduleRules)
            {
                Preconditions.ConfValueExists(moduleRule.name, "node/TEST/MODULE/name", context: context);
            }

            // Check the patch age.
            var patchAgeDays = (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalDays
                               - patchNode.patchCreationTimestamp / (24 * 60 * 60);

            if (patchAgeDays > 180)
            {
                DebugEx.Warning("Patch is too old: patch={0}, age={1} days", patchNode, patchAgeDays);
            }

            return(patchNode);
        }