Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A way to simplify defenvise sequence patches foradding fields

How you use it in the mods patch folder

<Operation Class="[YOUR C# MOD NAMESPACE].PatchOperationAddOrReplace">
    <xpath>/Defs/ThingDef[defName="Plant_TreeBirch"]/plant</xpath>
    <key>growDays</key>
    <value>22</value>
</Operation>

The class you need to add to your C# code

using System;
using System.Collections;
using System.Xml;
using Verse;

namespace [INSERT YOUR MOD NAMESPACE HERE]
{
    
    /*
    * A custom patch operation to simplify sequence patch operations when defensively adding fields
    * Code by Lanilor (https://github.com/Lanilor)
    * This code is provided "as-is" without any warrenty whatsoever. Use it on your own risk.
    */
    public class PatchOperationAddOrReplace : PatchOperationPathed
    {

        protected string key;
        private XmlContainer value;

        protected override bool ApplyWorker(XmlDocument xml)
        {
            XmlNode valNode = value.node;
            bool result = false;
            IEnumerator enumerator = xml.SelectNodes(xpath).GetEnumerator();
            try
            {
                while (enumerator.MoveNext())
                {
                    object obj = enumerator.Current;
                    result = true;
                    XmlNode parentNode = obj as XmlNode;
                    XmlNode xmlNode = parentNode.SelectSingleNode(key);
                    if (xmlNode == null)
                    {
                        // Add - Add node if not existing
                        xmlNode = parentNode.OwnerDocument.CreateElement(key);
                        parentNode.AppendChild(xmlNode);
                    }
                    else
                    {
                        // Replace - Clear existing children
                        xmlNode.RemoveAll();
                    }
                    // (Re)add value
                    xmlNode.AppendChild(parentNode.OwnerDocument.ImportNode(valNode.FirstChild, true));
                }
            }
            finally
            {
                IDisposable disposable = enumerator as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }
            }
            return result;
        }

    }

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment