Ludeon Forums

Ludeon Forums

  • January 20, 2020, 03:33:37 PM
  • Welcome, Guest
Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 4 5 [6]

Author Topic: A quick tutorial of xpathing and patching  (Read 36746 times)

Pelador

  • Colonist
  • ***
  • Posts: 139
  • Refugee
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #75 on: February 03, 2019, 11:54:14 PM »

There are a lot of scattered "tutorials" people have written, but they all seem to be missing bits and pieces.  I have found a reference to PatchOperationFindMod on the wiki.  Not many people seem to be using the wiki.  Is it accurate?

No one else seems to mention PatchOperationFindMod.  Does it actually exist?  If so, can anyone explain/show how it's used?

Does anyone want to update the wiki, or is that not a place people use?

--LWM

Syntax is as follows:

Code: [Select]
<Operation Class="PatchOperationFindMod">
<mods>
    <li>{Name of Mod as per About.xml def}</li>
      </mods>
        <match Class="PatchOperation{…}">
                <xpath>{xpath details}</xpath>
<value>
{vals…}
</value>
        </match>
<nomatch Class=”Patchoperation{…}>
                <xpath>{xpath details}</xpath>
<value>
{vals…}
</value>
</nomatch>
</Operation>

The optional <match /> and <nomatch /> are operations you can apply to your “OWN” mod based on whether the named mod is found.

I’ve found you cannot apply these within a patch sequence or embed a patch sequence into the match and nomatch nodes, so you have to specify multiple patch definitions if you need to do multiple different kinds of changes.

E.g.
Code: [Select]
<Operation Class="PatchOperationFindMod">
<mods>
<li>VGP Vegetable Garden</li>
      </mods>
        <match Class="PatchOperationReplace">
            <xpath>*/RecipeDef[defName="MakeMSMultiVitamins"]/ingredients</xpath>
            <value>
                    <ingredients>
<li>
<filter>
<thingDefs>
<li>Neutroamine</li>
</thingDefs>
</filter>
<count>1</count>
</li>
<li>
<filter>
<categories>
            <li>FruitFoodRaw</li>
          </categories>
</filter>
<count>5</count>
</li>
</ingredients>
</value>
</match>
    </Operation>

<Operation Class="PatchOperationFindMod">
      <mods>
        <li>VGP Vegetable Garden</li>
      </mods>
        <match Class="PatchOperationReplace">
            <xpath>*/RecipeDef[defName="MakeMSMultiVitamins"]/fixedIngredientFilter</xpath>
            <value>
<fixedIngredientFilter>
<thingDefs>
<li>Neutroamine</li>
</thingDefs>
<categories>
        <li>FruitFoodRaw</li>
      </categories>
</fixedIngredientFilter>
            </value>
        </match>
    </Operation>
Logged

LWM

  • Colonist
  • ***
  • Posts: 561
  • Little White Mouse
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #76 on: February 04, 2019, 01:11:04 AM »

Thank you very much!

I’ve found you cannot apply these within a patch sequence or embed a patch sequence into the match and nomatch nodes, so you have to specify multiple patch definitions if you need to do multiple different kinds of changes.

Oh, that's dismaying...I have a handful of places to patch, and a sequence would have been much easier.  But forewarned is forearmed.  And some peoples' alien races have four arms, so it's best to be prepared.

--LWM
Logged

LWM

  • Colonist
  • ***
  • Posts: 561
  • Little White Mouse
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #77 on: February 04, 2019, 12:03:04 PM »

Syntax is as follows:[...]
I’ve found you cannot apply these within a patch sequence or embed a patch sequence into the match and nomatch nodes, so you have to specify multiple patch definitions if you need to do multiple different kinds of changes.

Woohoo - I got my test compatibility patch working!

I also tested using a Sequence, and it worked!  So maybe something has changed?

But this does actually patch:

Code: [Select]
<Patch>
  <Operation Class="PatchOperationFindMod">
    <mods>
      <li>LWM's Deep Storage</li>
    </mods>
    <match Class="PatchOperationSequence">
      <operations>
        <li Class="PatchOperationReplace">
          <xpath>/Defs/ThingDef[defName="LWM_WeaponsLockerLocker"]/label</xpath>
          <value><label>Testing this.</label></value>
        </li>
        <li Class="etc"><actual stuff />
        </li>
      </operations>
    </match>
  </Operation>
</Patch>

Thanks!  I'll go add this detail to the wiki.
--LWM
Logged

LWM

  • Colonist
  • ***
  • Posts: 561
  • Little White Mouse
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #78 on: February 04, 2019, 12:34:57 PM »

I note that https://www.w3schools.com/xml/xpath_syntax.asp specifies that the expression "Defs" in an xpath would 'Select all nodes with the name "[Defs]."'  So it sounds like all xpaths should start with "/Defs" to avoid searching for "Defs" in any depth - am I correct?

--LWM
Logged

LWM

  • Colonist
  • ***
  • Posts: 561
  • Little White Mouse
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #79 on: April 29, 2019, 01:06:51 PM »

I note that https://www.w3schools.com/xml/xpath_syntax.asp specifies that the expression "Defs" in an xpath would 'Select all nodes with the name "[Defs]."'  So it sounds like all xpaths should start with "/Defs" to avoid searching for "Defs" in any depth - am I correct?

Note: I found in testing that /Defs was *slightly* faster than Defs.  Methodology:  https://github.com/lilwhitemouse/RimWorld-PatchSpeedTest

--LWM
Logged

Nerdygamer

  • Muffalo
  • *
  • Posts: 3
  • Refugee
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #80 on: July 31, 2019, 10:07:18 PM »

First time poster, so apologies if I'm out of line somewhere, but I'm having trouble xpathing into ThingDefs with parent names. I'm trying to adjust the blunt armor rating of marine helmets with a PatchOperationReplace. I have a rudimentary understanding of xpathing (thanks in part to this thread) and have a working patch to edit the values of room sizes. The following code works and is meant to serve as proof that I faintly know what I'm doing:
Code: [Select]
<Patch>
<Operation Class = "PatchOperationReplace">
<xpath>Defs/RoomStatDef[defName = "Space"]/scoreStages</xpath>
<value>
    <scoreStages>
[blah blah blah, snipped for space]
</scoreStages>
</value>
</Operation>
</Patch>

However, I cannot figure out how to use a replace command to change the value of a marine helmet's blunt protection. Everything I've tried just crashes the game immediately. I even used http://xmltoolbox.appspot.com/xpath_generator.html to "cheat" and write the code for me (you plug in the code, click on the line you wish to xpath to, and it spits out what you need), and even that doesn't work. My current code, which doesn't work, is as follows:
Code: [Select]
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationReplace">
    <xpath>Defs/ThingDef ParentName="ArmorHelmetMakeableBase"[defName = "Apparel_PowerArmorHelmet"]/statBases/ArmorRating_Blunt</xpath>
<value>
<ArmorRating_Blunt>0.4</ArmorRating_Blunt>
</value>
    </Operation>
</patch>

Help, please? I have no idea why my first example works and my second doesn't, but I've had trouble in the past when trying to xpath to an object that started with <ThingDef ParentName = blahblahblah>
« Last Edit: July 31, 2019, 10:11:00 PM by Nerdygamer »
Logged

LWM

  • Colonist
  • ***
  • Posts: 561
  • Little White Mouse
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #81 on: July 31, 2019, 10:50:21 PM »

You have an xpath of
Code: [Select]
<xpath>Defs/ThingDef ParentName="ArmorHelmetMakeableBase"[defName = "Apparel_PowerArmorHelmet"]/statBases/ArmorRating_Blunt</xpath>

But xpath operates on xml.  The node you are looking for is a "ThingDef" node which has an attribute of ParentName="blahblah".  But you don't care about that attribute - you're specifying the node based on the fact that it has a subnode of defName with value Apparel_PowerArmorHelmet.

So use this instead, and I think it will work:

Code: [Select]
<xpath>/Defs/ThingDef[defName = "Apparel_PowerArmorHelmet"]/statBases/ArmorRating_Blunt</xpath>

--LWM
PS - note that I put a "/" in front of the first Defs - it's sliiiightly faster to do it that way.
Logged

Nerdygamer

  • Muffalo
  • *
  • Posts: 3
  • Refugee
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #82 on: July 31, 2019, 11:23:08 PM »

Unfortunately, that still doesn't work.  Just trying to enable Core and my mod results in the game throwing up the "recovered from incompatible or corrupted mods error".  I have the mod folder, which has an "About" folder and a "Patches" folder.  In the "About" folder, I have an About.xml, which is as follows:
Code: [Select]
<?xml version="1.0" encoding="utf-8"?>
<ModMetaData>
  <name>Better Marine Helmets</name>
  <author>Nerdygamer1</author>
  <targetVersion>1.0</targetVersion>
  <description>Makes marine helmets competitive when compared to plasteel advanced helmets. Previously, plasteel advanced helmets had more health and better protection against blunt damage (despite the description suggesting otherwise). Now, advanced helmets have been given a gentle increase in both health and blunt protection, at the cost of ten extra plasteel (for a total cost of 50 plasteel; the same cost as a plasteel advanced helmet). Component requirements have not been changed.</description>
</ModMetaData>

In the "Patches" folder is my "Patches_Helmets.xml" which is as follows:
Code: [Select]
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationReplace">
    <xpath>/Defs/ThingDef[defName = "Apparel_PowerArmorHelmet"]/statBases/ArmorRating_Blunt</xpath>
<value>
<ArmorRating_Blunt>0.4</ArmorRating_Blunt>
</value>
    </Operation>
</patch>

And that's literally everything. The game throws an absolute fit when trying to start up with the mod enabled - checking the box automatically restarts the game, and upon booting up, I immediately get the error message; it's not even the debug log.
Logged

LWM

  • Colonist
  • ***
  • Posts: 561
  • Little White Mouse
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #83 on: August 01, 2019, 01:37:06 AM »

Your XML isn't valid!

You have a lowercase "patch" as your close tag instead of an uppercase.

I use emacs to do my editing, and one of the things it does for me is validate my xml automatically ^.^  I pasted the file in and it told me "Invalid" and gave the "patch" a nice noticeable orange.   I highly recommend a good editor that does that sort of thing for you.

...we've all done stupid things, so don't feel bad there....having an editor that catches (some) stupid mistakes means we can make more subtle ones that drive us up a limestone wall!

--LWM
Logged

Nerdygamer

  • Muffalo
  • *
  • Posts: 3
  • Refugee
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #84 on: August 01, 2019, 01:34:00 PM »

That worked!  Thank you so much for your help; you have no idea how long I spent googling, making minor changes, and testing last night.  I'm no stranger to formatting errors (and that was the first thing I double-checked - making sure I had all my brackets, my slashes, and making sure it was ThingDef), but my mistakes don't usually hang up the game so badly that I can't get a basic idea of what I did wrong from the debug log, and I didn't even think to check that my commands had the same casing :x

I'm looking into emacs right now.
« Last Edit: August 01, 2019, 01:36:27 PM by Nerdygamer »
Logged

LWM

  • Colonist
  • ***
  • Posts: 561
  • Little White Mouse
    • View Profile
Re: A quick tutorial of xpathing and patching
« Reply #85 on: August 01, 2019, 02:56:39 PM »

Emacs has a steeper learning curve than a lot of editors, I am willing to admit, but it's awesome.  If you want something simpler in Windows, look into Notepad++ - I think it does XML?  I'm sure google is your friend ;)

If you really feel like learning something new, there's also vi - which is better is still a hotly contested holy war.   ;D;P

Glad it worked for you!
Logged
Pages: 1 ... 4 5 [6]