Jump to content

XPath Modding Explanation Thread


sphereii

Recommended Posts

Something worth knowing, because I spent almost an hour trying to figure it out, is that the "or" and "and" commands can be a bit finicky.

The example given has:

property[@name=Magazine_items] or [@value=9mmBullet]

I have not tested this to see if it works, but I'll assume it does.

However, if you want to use "or" for different names, the syntax is actually different. It has to be like this instead:

property[@name=Magazine_items' or @name='Another_name]

Notice that now both names are inside the same bracket, and each is labeled with "@name". This does not work if the names are in separate brackets.

 

As an example, I made a "mod" that returns an empty jar from boiled foods:

<configs>
<append xpath="/items/item[@name='foodBoiledMeat'
or @name='foodCornBread'
or @name='foodCornOnTheCob'
or @name='foodVegetableStew'
or @name='foodEggBoiled'
or @name='foodBlueberryPie'
or @name='foodHoboStew'
or @name='foodMeatStew']
/property[@class='Action0']">
	<property name="Create_item" value="drinkJarEmpty"/>
</append>
</configs>

Link to comment
Share on other sites

Just wanted to confirm what @epigeios said, the syntax with operators is different than what is written in this tutorial.

 

For example this line:

 

<set xpath="/items/item/property[@name='Stacknumber'] and [@value='500']/@value">512</set>

 

will result in following error:

 

2018-11-21T10:41:53 9.789 EXC Error during parse of /items/item/property[@name='Stacknumber'] and [@value='500']/@value
yyException: irrecoverable syntax error
 at Mono.Xml.XPath.XPathParser.yyparse (yyInput yyLex) [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000] in <filename unknown>:0
Rethrow as XPathException: Error during parse of /items/item/property[@name='Stacknumber'] and [@value='500']/@value
 at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000] in <filename unknown>:0
 at System.Xml.XPath.XPathExpression.Compile (System.String xpath, IXmlNamespaceResolver nsmgr, IStaticXsltContext ctx) [0x00000] in <filename unknown>:0
 at System.Xml.XPath.XPathExpression.Compile (System.String xpath) [0x00000] in <filename unknown>:0
 at System.Xml.XPath.XPathNavigator.Compile (System.String xpath) [0x00000] in <filename unknown>:0
 at System.Xml.XmlNode.SelectNodes (System.String xpath, System.Xml.XmlNamespaceManager nsmgr) [0x00000] in <filename unknown>:0
 at System.Xml.XmlNode.SelectNodes (System.String xpath) [0x00000] in <filename unknown>:0
 at XmlFile.SetByXPath (System.String _xpath, System.Xml.XmlElement _xml, System.String _patchName) [0x00000] in <filename unknown>:0
 at XmlPatcher.singlePatch (.XmlFile _targetFile, System.Xml.XmlElement _patchElement, System.String _patchName) [0x00000] in <filename unknown>:0
 at XmlPatcher.PatchXml (.XmlFile _xmlFile, .XmlFile _patchXml, System.String _patchName) [0x00000] in <filename unknown>:0
 at XmlPatcher.LoadAndPatchConfig (System.String _configName) [0x00000] in <filename unknown>:0
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
Logger:masterLogException(Exception)
Logger:Exception(Exception)
Log:Exception(Exception)
XmlPatcher:LoadAndPatchConfig(String)
<loadSingleXml>c__Iterator1:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

 

should be this instead:

 

<set xpath="/items/item/property[@name='Stacknumber' and @value='500']/@value">512</set>

 

same with "or".

Link to comment
Share on other sites

Just wanted to confirm what @epigeios said, the syntax with operators is different than what is written in this tutorial.

 

For example this line:

 

<set xpath="/items/item/property[@name='Stacknumber'] and [@value='500']/@value">512</set>

 

will result in following error:

 

2018-11-21T10:41:53 9.789 EXC Error during parse of /items/item/property[@name='Stacknumber'] and [@value='500']/@value
yyException: irrecoverable syntax error
 at Mono.Xml.XPath.XPathParser.yyparse (yyInput yyLex) [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000] in <filename unknown>:0
Rethrow as XPathException: Error during parse of /items/item/property[@name='Stacknumber'] and [@value='500']/@value
 at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000] in <filename unknown>:0
 at System.Xml.XPath.XPathExpression.Compile (System.String xpath, IXmlNamespaceResolver nsmgr, IStaticXsltContext ctx) [0x00000] in <filename unknown>:0
 at System.Xml.XPath.XPathExpression.Compile (System.String xpath) [0x00000] in <filename unknown>:0
 at System.Xml.XPath.XPathNavigator.Compile (System.String xpath) [0x00000] in <filename unknown>:0
 at System.Xml.XmlNode.SelectNodes (System.String xpath, System.Xml.XmlNamespaceManager nsmgr) [0x00000] in <filename unknown>:0
 at System.Xml.XmlNode.SelectNodes (System.String xpath) [0x00000] in <filename unknown>:0
 at XmlFile.SetByXPath (System.String _xpath, System.Xml.XmlElement _xml, System.String _patchName) [0x00000] in <filename unknown>:0
 at XmlPatcher.singlePatch (.XmlFile _targetFile, System.Xml.XmlElement _patchElement, System.String _patchName) [0x00000] in <filename unknown>:0
 at XmlPatcher.PatchXml (.XmlFile _xmlFile, .XmlFile _patchXml, System.String _patchName) [0x00000] in <filename unknown>:0
 at XmlPatcher.LoadAndPatchConfig (System.String _configName) [0x00000] in <filename unknown>:0
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
Logger:masterLogException(Exception)
Logger:Exception(Exception)
Log:Exception(Exception)
XmlPatcher:LoadAndPatchConfig(String)
<loadSingleXml>c__Iterator1:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

 

should be this instead:

 

<set xpath="/items/item/property[@name='Stacknumber' and @value='500']/@value">512</set>

 

same with "or".

 

Thank you both! I'll update the posts.

Link to comment
Share on other sites

First i want to congratulate u for making this amazing tool/way to mod your game, but...

 

I get errors cause i mistype something in the vanilla files(fixing it with trial and error). Your way is another beast.

It is not very simple (ofc it needs to be complex for flexibility i know) and when i try a very simple mod i do not know if

i mistype or forgot a </rect> or i mistype the commands to do the appends etc.

 

Now i'll ask for more....is it possible to have a modded lets say windows.xml and a vanilla and a tool to compare and automate the xpath method or a way to append the values in the vanilla xml and see where the problem is?

 

I'll eventually learn how to use it but now i struggle to find out why for example why my hunger bar is not green and flashing from green to gray rapidly(solved it but it took me 1 day) ;p

 

I know i ask ALOT.

Link to comment
Share on other sites

No problem and thank you for the tutorial :)

 

I noticed another problem, this time with your "not" example. Using the syntax you provided I tried this:

 

<set xpath="/items/item[not contains(@name, 'Empty'))]/property[@name='Stacknumber']/@value">64</set>

 

and this give following error:

 

2018-11-21T14:12:50 10.898 EXC invalid operator name: 'contains'
XPathException: invalid operator name: 'contains'
 at Mono.Xml.XPath.Tokenizer.ParseIdentifier () [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.Tokenizer.ParseToken () [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.Tokenizer.advance () [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.XPathParser.yyparse (yyInput yyLex) [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000] in <filename unknown>:0
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
Logger:masterLogException(Exception)
Logger:Exception(Exception)
Log:Exception(Exception)
XmlPatcher:LoadAndPatchConfig(String)
<loadSingleXml>c__Iterator1:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

 

proper example should look like this

 

<set xpath="/entity_classes/entity_class[not (contains(@name, 'zombie'))]/property[@name='Class']/@value">EntityZombieSDX, Mods</set>

 

I made a combination of two conditions, you can include it in your examples if you like. This will set stack number to 64 for all drinks in jars but will leave drinkJarEmpty at it's default stack number:

 

<set xpath="/items/item[starts-with(@name, 'drinkJar') and not(contains(@name, 'Empty'))]/property[@name='Stacknumber']/@value">64</set>

Link to comment
Share on other sites

First i want to congratulate u for making this amazing tool/way to mod your game, but...

 

I get errors cause i mistype something in the vanilla files(fixing it with trial and error). Your way is another beast.

It is not very simple (ofc it needs to be complex for flexibility i know) and when i try a very simple mod i do not know if

i mistype or forgot a </rect> or i mistype the commands to do the appends etc.

 

Now i'll ask for more....is it possible to have a modded lets say windows.xml and a vanilla and a tool to compare and automate the xpath method or a way to append the values in the vanilla xml and see where the problem is?

 

I'll eventually learn how to use it but now i struggle to find out why for example why my hunger bar is not green and flashing from green to gray rapidly(solved it but it took me 1 day) ;p

 

I know i ask ALOT.

 

I'm sorry, but there's no tool yet that will generate an xpath file. There are online generators that you can use to help build your xpath. I haven't linked to them yet, since they sometimes do strange things, like using index values.

Link to comment
Share on other sites

No problem and thank you for the tutorial :)

 

I noticed another problem, this time with your "not" example. Using the syntax you provided I tried this:

 

<set xpath="/items/item[not contains(@name, 'Empty'))]/property[@name='Stacknumber']/@value">64</set>

 

and this give following error:

 

2018-11-21T14:12:50 10.898 EXC invalid operator name: 'contains'
XPathException: invalid operator name: 'contains'
 at Mono.Xml.XPath.Tokenizer.ParseIdentifier () [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.Tokenizer.ParseToken () [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.Tokenizer.advance () [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.XPathParser.yyparse (yyInput yyLex) [0x00000] in <filename unknown>:0
 at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000] in <filename unknown>:0
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
Logger:masterLogException(Exception)
Logger:Exception(Exception)
Log:Exception(Exception)
XmlPatcher:LoadAndPatchConfig(String)
<loadSingleXml>c__Iterator1:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

 

proper example should look like this

 

<set xpath="/entity_classes/entity_class[not (contains(@name, 'zombie'))]/property[@name='Class']/@value">EntityZombieSDX, Mods</set>

 

I made a combination of two conditions, you can include it in your examples if you like. This will set stack number to 64 for all drinks in jars but will leave drinkJarEmpty at it's default stack number:

 

<set xpath="/items/item[starts-with(@name, 'drinkJar') and not(contains(@name, 'Empty'))]/property[@name='Stacknumber']/@value">64</set>

 

Thank you! I updated the post.

Link to comment
Share on other sites

I get errors cause i mistype something in the vanilla files(fixing it with trial and error). Your way is another beast.

It is not very simple (ofc it needs to be complex for flexibility i know) and when i try a very simple mod i do not know if

i mistype or forgot a </rect> or i mistype the commands to do the appends etc.

For your generic XML issues I recommend using e.g. Notepad++ with the XML plugin. It will tell you when the general XML structure is borked (like if you forget to close an XML element, mismatching open and close names etc).

Link to comment
Share on other sites

(Have not tested this yet - will attempt to do so when I get home tonight)

 

How about adding/changing things within the text files such as the locilization.txt?

 

I do not want to take anything away from this wonderful addition so first let me say thank you for putting the time and effort into making this happen.

 

That said I cant stress enough the importance of the Localization being something we have control over using xpath. Unfortunately I can not use xpath as I wished i could have due to this. So many of my mods include new items and blocks and require descriptions that by having to still do them by hand in the original file, as well as having to instruct people HOW to copy the Localization into their vanilla install negates the use of this for me and some others.

 

Also the issue will arise where someone like myself and others include vanilla Localizations in their modlets, and each will contain DIFFERENT entries that when the user copies into their files will overwrite the other. I know this may not seem like a priority but descriptions and conformity in naming conventions almost require we be able to include our own Localization in mods.

Link to comment
Share on other sites

I dont know if I found a bug or not but I was messing around with combinations of modlets and Ravenhearst. It seems that if I add a block with a custom asset into the xml, and then add a modlet that also has a custom block it OVERWRITE the Ravenhearst one.

 

For example I have a drying rack in Ravenhearst. I added it to 17 using the old method. I then went to drop my farming modlet in that adds wheat. My drying racks disappeared and became a wheat plant.

 

Mentioning this because for mods like Walkers and Darkness Falls that have complete overhauls this could cause massive issues if players install modlets on top of it and it removes our items. Was this intentional?

 

If it is I think it should be explicitly stated that this is how it works otherwise somewhere along the line someone is going to install something from the Launcher and then try to add modlets and its going to wreck their games.

Link to comment
Share on other sites

I dont know if I found a bug or not but I was messing around with combinations of modlets and Ravenhearst. It seems that if I add a block with a custom asset into the xml, and then add a modlet that also has a custom block it OVERWRITE the Ravenhearst one.

 

For example I have a drying rack in Ravenhearst. I added it to 17 using the old method. I then went to drop my farming modlet in that adds wheat. My drying racks disappeared and became a wheat plant.

 

Mentioning this because for mods like Walkers and Darkness Falls that have complete overhauls this could cause massive issues if players install modlets on top of it and it removes our items. Was this intentional?

 

If it is I think it should be explicitly stated that this is how it works otherwise somewhere along the line someone is going to install something from the Launcher and then try to add modlets and its going to wreck their games.

 

That isn't the expected results. Can you send me the files through discord, and I'll take a look? Are you using <append> or <insertBefore> and <insertAfter> ?

 

- - - Updated - - -

 

I do not want to take anything away from this wonderful addition so first let me say thank you for putting the time and effort into making this happen.

 

That said I cant stress enough the importance of the Localization being something we have control over using xpath. Unfortunately I can not use xpath as I wished i could have due to this. So many of my mods include new items and blocks and require descriptions that by having to still do them by hand in the original file, as well as having to instruct people HOW to copy the Localization into their vanilla install negates the use of this for me and some others.

 

Also the issue will arise where someone like myself and others include vanilla Localizations in their modlets, and each will contain DIFFERENT entries that when the user copies into their files will overwrite the other. I know this may not seem like a priority but descriptions and conformity in naming conventions almost require we be able to include our own Localization in mods.

 

The testing version of SDX has removed the ability to merge the xpath, but it kept the ability to apply localization.

 

If your SDX mod folder is like this:

 

JaxTeller718/Config/
JaxTeller718/Scripts/
JaxTeller718/Text/
JaxTeller718/Resources/

 

It will copy the Config and Resource scripts over into the Game's Mods/JaxTeller718/ as-is, build and apply the scripts, and do the localization merge.

 

It's definitely not ideal, and I believe there's plans to include native support for localization, but we just aren't there yet.

Link to comment
Share on other sites

Hi!

 

Can you send me an example of ModInfo.xml file please ?

 

Sure

 

<?xml version="1.0" encoding="UTF-8" ?>
<xml>
<ModInfo>
	<Name value="SphereII_PG13" />
	<Description value="This modlet tries to make the game a bit more PG, by switching out the stripper model with a nurse." />
	<Author value="sphereii" />
	<Version value="1.0.0" />
</ModInfo>
</xml>

Link to comment
Share on other sites

That said I cant stress enough the importance of the Localization being something we have control over using xpath. Unfortunately I can not use xpath as I wished i could have due to this. So many of my mods include new items and blocks and require descriptions that by having to still do them by hand in the original file, as well as having to instruct people HOW to copy the Localization into their vanilla install negates the use of this for me and some others.

 

 

While you may not be able to modify the locilization file. I have had decent success in modifying a description directly and bypassing the localization file (if it cant fidn it in the locilization fiel it prints it as is ingame)

 

 

It may not be perfect for all cases, but my limited use of it works well enough until propr localization modding is implemented.

Link to comment
Share on other sites

This is AWESOME! Will make the adding of tweaks and personal changes so much easier!

 

now to learn it haha

 

Ok how do i add in new Item? I want to create the herbal bandage. Using Chrysanthemum and goldenrod, and NitratePowder. I want to make a first aid bandage that works like vanilla, but half strength.

Link to comment
Share on other sites

Playing around with it a bit, really like it.

I hope we get more functions, like 'mult', 'add', 'sub'.

 

For now I will use stacksize selectors:

<configs>

 <set xpath="/items/item[contains(@name,'resource')]/property[
               @name='Stacknumber'
               and @value > 900
             ]/@value">20000</set>

 <set xpath="/items/item[contains(@name,'resource')]/property[
               @name='Stacknumber'
               and @value <= 900
               and @value > 400
             ]/@value">2000</set>

 <set xpath="/items/item[contains(@name,'resource')]/property[
               @name='Stacknumber'
               and @value <= 400
               and @value > 100
             ]/@value">1000</set>

 <set xpath="/items/item[contains(@name,'resource')]/property[
               @name='Stacknumber'
               and @value < 100
             ]/@value">250</set>

</configs>

Link to comment
Share on other sites

Can you link to the plugin?

 

If you use the 32-bit version of NotePad++, go to Plugins -> Plugin Manager. Do any update it asks for. Then search in the available list for XML Tools.

 

I'm not sure if the 64-bit version of Notepad++ has the Plugin Manager working yet; it may need manual downloads and file placements.

Link to comment
Share on other sites

Attempting to Add in Valmars Fuel log, requires adding in a new recipe and Item. Heres what i did....

 

2 files in config folder

recipes has

 

<configs>
    <append xpath="/recipes">

               <recipe name="fuelLog" count="1">
                  <ingredient name="resourceWood" count="20"/>
                  <ingredient name="resourceTallow" count="1" />
               </recipe>

	</append>
</configs>

 

And Items has

 

<configs>
    <append xpath="/items">

           	<item name="fuelLog">

                   <property name="Meshfile" value="Items/Misc/sackPrefab"/>
                   <property name="DropMeshfile" value="Items/Misc/sack_droppedPrefab"/>
   	               <property name="Material" value="Mwood"/>
                   <property name="HoldType" value="45"/>
				   <property name="DescriptionKey" value="fuelLogDesc"/>
	               <property name="Stacknumber" value="50" />
				   	<property name="Weight" value="5"/>
   	               <property name="SellableToTrader" value="true"/>
	               <property name="EconomicValue" value="34"/>
	               <property name="FuelValue" value="580" />
                   <property name="Group" value="Resources,Basics"/>
                   <property name="CraftingSkillGroup" value="craftSkillScience"/>
				   <property name="CraftingIngredientTime" value="0.25"/>


             </item>

	</append>
</configs>

 

Hows it look?

 

Holy crap it worked lol I had to edit the main localization file right? no way yet to use xpath to edit those yet?

Edited by wolverine576 (see edit history)
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...