/// <inheritdoc />
        public bool OnListNode(
            int index,
            object value,
            ListValueReflection reflection,
            NodeReflection nodeReflection,
            out object newValue
            )
        {
            if (index == 0 && IsPatch)
            {
                Node.AddNode(string.IsNullOrEmpty(reflection.Name)
                                 ? $"!{reflection.NodeId},*"
                                 : $"!{reflection.NodeId}[{reflection.Name}],*");
            }

            newValue = default;
            var save = new SaveVisitor
            {
                IsPatch = false,
                Node    = new ConfigNode()
            };

            nodeReflection.Save(save, value);

            if (save.Node.HasData)
            {
                Serialization.AddNode(Node, save.Node, nodeReflection.Id, reflection.Name);
            }

            return(false);
        }
        private static void SaveConfigs(
            string prefix,
            bool isPatch     = true,
            string extension = ".cfg",
            bool force       = false
            )
        {
            var node = new ConfigNode();
            var save = new SaveVisitor
            {
                IsPatch = isPatch,
                Node    = node
            };

            foreach (KeyValuePair <string, ReflectedConfig> pair in ConfigReflection.Instance.Configs)
            {
                if (!pair.Value.Reflection.ShouldSave)
                {
                    continue;
                }

                pair.Value.Reflection.Save(save, pair.Value.Instance);

                if (!save.Node.HasData)
                {
                    continue;
                }

                string path = PathUtil.Combine(KSPUtils.GameDataPath, $"{prefix}_{pair.Key}{extension}");

                if (!pair.Value.Reflection.AllowMultiple)
                {
                    Serialization.MakeTopNode(node, pair.Key, null, isPatch);
                }

                string nodeStr = node.ToString();

                if (lastConfigs.TryGetValue(pair.Key, out string oldStr))
                {
                    lastConfigs[pair.Key] = nodeStr;
                }
                else
                {
                    lastConfigs.Add(pair.Key, nodeStr);
                }

                // only write if requested or if the node has been modified, first time oldStr should be null so can be skipped
                if (force || (!string.IsNullOrEmpty(oldStr) && nodeStr != oldStr))
                {
                    FARLogger.DebugFormat("Saving {0} config to {1}:\n{2}\n\n{3}", pair.Key, path, oldStr, nodeStr);
                    System.IO.File.WriteAllText(path, nodeStr);
                }
                else
                {
                    FARLogger.DebugFormat("{0} does not require saving", pair.Key);
                }

                node.ClearData();
            }
        }
        /// <inheritdoc />
        public bool OnNode(object value, NodeReflection reflection, out object newValue)
        {
            newValue = default;
            var save = new SaveVisitor
            {
                IsPatch = IsPatch,
                Node    = new ConfigNode()
            };

            reflection.Save(save, value);

            if (save.Node.HasData)
            {
                Serialization.AddNode(Node, save.Node, reflection.Id, reflection.Name, IsPatch);
            }

            return(false);
        }