Modding Tutorials/XML Defs

From RimWorld Wiki
Revision as of 12:29, 24 January 2019 by Mehni (talk | contribs) (Filling some great big knowledge gaps)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Modding Tutorials

This tutorial will tell you about the structure of Defs. It will explain the link between C# and Defs, as well as go over some common errors.

Requirements

  1. You've read XML file structure.
  2. A basic understanding of XML is recommended.
  3. Some C# knowledge is helpful for a deeper understanding of the behind-the-scenes workings, but not required.

Structure

As previously established, the root node of all defs in the game is <Defs>. RimWorld will try to interpret everything between the opening tag of <Defs> and <Defs> as a type of def. These types correspond to a C# class which inherits from the Def class. For example

<Defs>
	<ThingDef>
	</ThingDef>
</Defs>


points to the ThingDef class, which in C# inherits from the Def class. All XML nodes inside the <ThingDef> tag are a field in the ThingDef class. These fields can hold references to simple values like integers or strings. defName is one such string in the base Def class, so we'll give our ThingDef a defName of SomeName. A field can also contain more complex values like IngestibleProperties. The XML tag (and field name) that corresponds to IngestibleProperties is called ingestible. IngestibleProperties also has fields of its own, and these would go inside the ingestible tag, as a childnode. IngestibleProperties has a field of type SoundDef with the name of ingestSound. RimWorld resolves these by both Type and defName. Fleshing out our example with an ingestSound, our example now looks like this:

<Defs>
	<ThingDef>
		<defName>SomeName</defName>
		<ingestible>
			<ingestSound>Slurp</ingestSound>
		</ingestible>
	</ThingDef>
</Defs>


The rootnode of our example is <Defs>. The first childnode of <Defs> is <ThingDef>. <defName> and <ingestible> are both childnodes of <ThingDef> and they are siblingnodes of each other. Proper XML formatting will help you a lot in distinguishing the hierarchy of your XML. You can save yourself a lot of hassle if you get a text editor (or plugin) which can auto-format XML for you.

Common errors

For beginning coders, the most common errors are formatting or syntax errors. A missing bracket, unclosed tag, empty file - these can all be avoided by using the proper tools. Get a text editor (or plug-in) that highlights or warns for these basic issues. RimWorld will not warn you: at best it will overload you with errors, at worst it will refuse to start.

Other common errors are related to resolving cross-references. For instance: def A wants to use def B, but def B can't be found. These cross-references are by defName. Both Type and defName have to match. In our earlier example, if there isn't a SoundDef with the Slurp defName, the game will log the following error:

       Could not resolve cross-reference: No SoundDef named Slurp found to give to ThingDef SomeName.

If the game can't find a cross-reference in a list, the error is slightly different:

       Could not resolve cross-reference to Verse.ThingCategoryDef named BuldingsPower (wanter=thingCategories)

where wanter=thingCategories is an optional addition, but it's the xml tag containing the misspelled "BuildingsPower".

Other errors are:

  • Defining the same field/tag twice
       XML RimWorld.ThoughtDef defines the same field twice: stackLimit.
       Field contents: 1.
       Whole XML: <A lot of XML>

In this example, there is a ThoughtDef with two stackLimit entries. Likely the result of two mods patching the same Def. The first mod wins.

  • Missing a Type
       Could not find type named TurretExtensions.CompProperties_Upgradable from node <A lot of XML>

This happens when an XML mod refers to a type which isn't loaded. In practice, a missing (DLL) dependency, a (DLL) dependency which couldn't be loaded due to earlier errors, or an outdated mod.

  • Referencing a non-existing field
        XML error: <costStaffCount>50</costStaffCount> doesn't correspond to any field in type ThingDef. Context: <ThingDef ParentName="SculptureBase"><defName>SculptureSmall</defName><label>small sculpture</label><description>An artistic sculpture.</description><stuffCategories><li>Metallic</li><li>Woody</li><li>Stony</li></stuffCategories><costStaffCount>50</costStaffCount></ThingDef>

This happens when the parentnode (in this case ThingDef) does not contain an entry for the costStaffCount tag. This could be caused by a simple typo, by putting the tag in the wrong node, by a missing dependency, as a result of earlier errors, or an outdated mod. XML can only correspond to fields that are defined in C#.

Note about (solving) XML errors

XML errors cascade. Behind the scenes, RimWorld combines all Defs inside one massive XML document. If one <tag> is missing its closing </tag>, none of the XML will be readable by the parser and you will be greeted by a wall of red errors. Find the first XML error, and fix that one. Do not go chasing the other errors just yet. Reload the game, then fix the next error (if any).