Difference between revisions of "Modding Tutorials/ConfigErrors"

From RimWorld Wiki
Jump to navigation Jump to search
(Create page)
m
Line 17: Line 17:
 
</source>
 
</source>
  
Let's assume we have our new Def here and it has a special value that is only allowed to be in the range of 0 - 10, with the default value being 4.
+
Let's say we have our new Def here and it has a special value that is only allowed to be in the range of 0 - 10, with the default value being 4.
  
Anyone can easily add a new ''MyOwnDef'' to your mod, and you could put documentation out there in the hopes that someone reads it and properly only assigns values between 0-10 to your ''someValue'' or that they stumble over your tiny comment.
+
Anyone can easily add a new ''MyOwnDef'' to your mod or modify an existing one with a patch operation. You could put documentation out there in the hopes that someone reads it and properly only assigns values between 0-10 to your ''someValue'', or that they stumble over your tiny comment.
  
 
Or you can provide ConfigErrors that yell at anyone trying to use a value that you don't explicitly allow for your own Def.
 
Or you can provide ConfigErrors that yell at anyone trying to use a value that you don't explicitly allow for your own Def.
Line 40: Line 40:
 
</source>
 
</source>
  
To break it down, ''Def'' already implements a virtual ConfigErrors(), which we can override in our ''MyOwnDef''. Because this is a virtual IEnumerable, it makes sense to call the base.ConfigErrors(), which will run the basic ''Def'' validation (like setting a defName) - and then yield our own desired config errors.
+
To break it down, ''Def'' already implements a virtual ConfigErrors(), which we can override in our ''MyOwnDef''. Because this is a virtual IEnumerable, it makes sense to call the base.ConfigErrors(), which will run the basic ''Def'' validation (like setting a ''defName'') - and then yield our own desired config errors.
  
I personally dislike numbers anywhere in code, so I define constant values and compare to those, you could theoretically just compare directly to your desired limits.
+
I personally dislike numbers anywhere in code, so I define constant values and compare to those, you could just compare directly to your desired limits.
  
 
===Notes===
 
===Notes===
In case you are a new comer, here are some things you may want to research via Google:
+
In case you are a newcomer, here are some things you may want to research via Google:
 +
 
 +
MyOwnDef : Def
 +
Subclassing an existing Type, in this case making a subclass of ''Def'' named ''MyOwnDef''
  
 
  public override
 
  public override

Revision as of 12:19, 3 September 2022

Preamble

Who this is for: Modders that implement their own XML-loading classes, like new Def.

ConfigErrors are the red errors you are presented when the game launches and detects erroreous XML data, like a required field not being set or a value of a field being out of its range.

Chances are, you have seen plenty of these errors in the past, some may consider them an annoyance, but if done right, they inform both the modder and the user of potentially critical issues in the XML data provided.

Subclassing Def

The most applicable example of ConfigErrors is subclassing Def.

public class MyOwnDef : Def
{
    float someValue = 4f;  // only allow values bettwen 0-10
}

Let's say we have our new Def here and it has a special value that is only allowed to be in the range of 0 - 10, with the default value being 4.

Anyone can easily add a new MyOwnDef to your mod or modify an existing one with a patch operation. You could put documentation out there in the hopes that someone reads it and properly only assigns values between 0-10 to your someValue, or that they stumble over your tiny comment.

Or you can provide ConfigErrors that yell at anyone trying to use a value that you don't explicitly allow for your own Def.

public class MyOwnDef : Def
{
    float someValue = 4f;
    const float minSomeValue = 0f;
    const float maxSomeValue = 10f;

    public override IEnumerable<string> ConfigErrors()
    {
        foreach(string error in base.ConfigErrors())
            yield return error;
        if(someValue < minSomeValue || someValue > maxSomeValue)
            yield return $"someValue is {someValue}, which is out of the valid range of {minSomeValue} - {maxSomeValue}!";
    }
}

To break it down, Def already implements a virtual ConfigErrors(), which we can override in our MyOwnDef. Because this is a virtual IEnumerable, it makes sense to call the base.ConfigErrors(), which will run the basic Def validation (like setting a defName) - and then yield our own desired config errors.

I personally dislike numbers anywhere in code, so I define constant values and compare to those, you could just compare directly to your desired limits.

Notes

In case you are a newcomer, here are some things you may want to research via Google:

MyOwnDef : Def

Subclassing an existing Type, in this case making a subclass of Def named MyOwnDef

public override

Overriding a base member, in this case a public Method

yield return 

Returns a single item in a collection, only works on methods with the method signature IEnumerable<T>

$"someValue is {someValue}, which is out of the valid range of {minSomeValue} - {maxSomeValue}!";

The string here uses String Interpolation, which is a quick and easy way of embedding variables into a logging string