Difference between revisions of "Modding:Modder Guide/APIs/Config"

From Stardew Valley Wiki
Jump to navigation Jump to search
(move content from Modding:Modder Guide/APIs (main author is Pathoschild, with contributions from KNakamura and Kalthramis))
 
 
(18 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 
{{../../header}}
 
{{../../header}}
  
===Configuration===
+
You can let users configure your mod through a standard <samp>config.json</samp> file. SMAPI will automatically create the file and take care of reading, normalising, and updating it.
You can let users configure your mod through a <tt>config.json</tt> file. SMAPI will automatically create the file and take care of reading, normalising, and updating it.
 
  
<dl>
+
==Config model==
<dt>Basic configuration</dt>
+
===Creating a config model===
<dd>Here's the simplest way to use <tt>config.json</tt>:
+
The ''config model'' is a C# class you create, with properties representing the settings you want to store. It can contain almost anything from a few boolean fields to a complex object graph (though you should try to keep things simple for players). Here's a simple config model:
 +
<syntaxhighlight lang="c#">
 +
public sealed class ModConfig
 +
{
 +
  public bool ExampleBoolean { get; set; }
 +
  public int ExampleNumber { get; set; }
 +
}
 +
</syntaxhighlight>
 +
 
 +
That model would be saved to <samp>config.json</samp> with this content:
 +
<syntaxhighlight lang="json">
 +
{
 +
  "ExampleBoolean": false,
 +
  "ExampleNumber": 0
 +
}
 +
</syntaxhighlight>
  
<ol>
+
These properties must be public.
<li>Create your model. This is just a C# class with properties for the config options you want, and it can contain almost anything from a few boolean fields to a complex object graph (You should try to keep it simple for your users, though).
 
<br />You can set defaults directly:
 
  
<source lang="c#">
+
===Default values===
class ModConfig
+
You can set default values in your data model:
 +
<syntaxhighlight lang="c#">
 +
public sealed class ModConfig
 
{
 
{
 
   public bool ExampleBoolean { get; set; } = true;
 
   public bool ExampleBoolean { get; set; } = true;
   public float ExampleFloat { get; set; } = 0.5f;
+
   public int ExampleNumber { get; set; } = 5;
 
}
 
}
</source>
+
</syntaxhighlight>
  
...or with a constructor:
+
...or set defaults with a constructor:
  
<source lang="c#">
+
<syntaxhighlight lang="c#">
class ModConfig
+
public sealed class ModConfig
 
{
 
{
 
   public bool ExampleBoolean { get; set; }
 
   public bool ExampleBoolean { get; set; }
   public float ExampleFloat { get; set; }
+
   public int ExampleNumber { get; set; }
  
 
   public ModConfig()
 
   public ModConfig()
 
   {
 
   {
 
       this.ExampleBoolean = true;
 
       this.ExampleBoolean = true;
       this.ExampleFloat = 0.5f;
+
       this.ExampleNumber = 5;
 
   }
 
   }
 
}
 
}
</source></li>
+
</syntaxhighlight>
  
<li>In your <tt>ModEntry::Entry</tt> method, add this line to read the config options:
+
==Using the config file==
 +
To read the <samp>config.json</samp> (SMAPI will create it automatically):
  
<source lang="c#">
+
<ol>
ModConfig config = helper.ReadConfig<ModConfig>();
+
<li>Create your [[#Config model|config model]].</li>
</source>
+
<li>Access the config values in your <samp>ModEntry</samp> class:
 +
<syntaxhighlight lang="c#">
 +
/// <summary>The main entry point for the mod.</summary>
 +
internal sealed class ModEntry : Mod
 +
{
 +
    /*********
 +
    ** Properties
 +
    *********/
 +
    /// <summary>The mod configuration from the player.</summary>
 +
    private ModConfig Config;
  
Values are then accessible through the value config. Example:
+
 
<source lang="c#">
+
    /*********
public class ModEntry : Mod
+
    ** Public methods
{
+
    *********/
  public override void Entry(IModHelper helper)
+
    /// <summary>The mod entry point, called after the mod is first loaded.</summary>
  {
+
    /// <param name="helper">Provides simplified APIs for writing mods.</param>
    ModConfig config = helper.ReadConfig<ModConfig>();
+
    public override void Entry(IModHelper helper)
    float exampleF = config.ExampleFloat;
+
    {
  }
+
        this.Config = this.Helper.ReadConfig<ModConfig>();
 +
        bool exampleBool = this.Config.ExampleBoolean;
 +
    }
 
}
 
}
</source>
+
</syntaxhighlight>
 
</li>
 
</li>
 
</ol>
 
</ol>
  
That's it! When the player launches the game, SMAPI will create the <tt>config.json</tt> file automatically if it doesn't exist yet, using the default config options you provided in your model. If you need to edit and save the config, you can use <tt>helper.WriteConfig(config)</tt>. You can access the helper in other methods using <tt>this.Helper</tt>.</dd>
+
That's it! When the player launches the game, SMAPI will create the <samp>config.json</samp> file automatically if it doesn't exist yet, using the default config options you provided in your model. If you need to save some changes, you can use <samp>this.Helper.WriteConfig(this.Config)</samp>.
  
<dt>Custom JSON files</dt>
+
Note that <samp>ReadConfig</samp> will raise an exception if the user does not provide a valid JSON.
<dd>
 
Sometimes one <tt>config.json</tt> isn't enough, or you need to store data that's not meant to be edited by the user. This is pretty easy using the <tt>ModHelper</tt>:
 
  
<ol>
+
==Keybind settings==
<li>Create your model (just like the previous section).</li>
+
: {{main article|Modding:Modder Guide/APIs/Input}}
<li>In your mod code, use <tt>this.Helper</tt> to read and write to a named file:
 
  
<source lang="c#">
+
You can use SMAPI's [[Modding:Modder Guide/APIs/Input#KeybindList|<samp>KeybindList</samp>]] in your model to let users configure keybinds. This automatically supports multi-key or alternative bindings (''e.g.,'' to support split-screen mode):
// read file
 
var model = this.Helper.ReadJsonFile<ModData>("data.json") ?? new ModData();
 
  
// save file (if needed)
+
<syntaxhighlight lang="c#">
this.Helper.WriteJsonFile("data.json", model);
+
class ModConfig
</source>
+
{
 +
  public KeybindList ToggleKey { get; set; } = KeybindList.Parse("LeftShift + F2, LeftTrigger");
 +
}
 +
</syntaxhighlight>
  
Note that <tt>ReadJsonFile</tt> will return <tt>null</tt> if the file doesn't exist. The above example will create a default instance if that happens; if you don't want to do that, just remove the <code>?? new ModData()</code> part.</li>
+
The value is automatically written/parsed in the <samp>config.json</samp> file as a string:
</ol></dd>
+
<syntaxhighlight lang="json">
 
+
{
<dt>Per-save JSON files</dt>
+
  "ToggleKey": "LeftShift + F2, LeftTrigger"
<dd>
+
}
You can create per-save files by using the save ID in the name. If you specify a folder path (relative to your mod folder), SMAPI will create the folders automatically if needed.
+
</syntaxhighlight>
 
 
For example, here's a typical per-save data file:
 
 
 
<source lang="c#">
 
// read file
 
var model = this.Helper.ReadJsonFile<ModData>($"data/{Constants.SaveFolderName}.json") ?? new ModData();
 
 
 
// write file (if needed)
 
this.Helper.WriteJsonFile($"data/{Constants.SaveFolderName}.json", model);
 
</source></dd>
 
</dl>
 

Latest revision as of 02:07, 26 May 2023

Creating SMAPI mods SMAPI mascot.png


Modding:Index

You can let users configure your mod through a standard config.json file. SMAPI will automatically create the file and take care of reading, normalising, and updating it.

Config model

Creating a config model

The config model is a C# class you create, with properties representing the settings you want to store. It can contain almost anything from a few boolean fields to a complex object graph (though you should try to keep things simple for players). Here's a simple config model:

public sealed class ModConfig
{
   public bool ExampleBoolean { get; set; }
   public int ExampleNumber { get; set; }
}

That model would be saved to config.json with this content:

{
   "ExampleBoolean": false,
   "ExampleNumber": 0
}

These properties must be public.

Default values

You can set default values in your data model:

public sealed class ModConfig
{
   public bool ExampleBoolean { get; set; } = true;
   public int ExampleNumber { get; set; } = 5;
}

...or set defaults with a constructor:

public sealed class ModConfig
{
   public bool ExampleBoolean { get; set; }
   public int ExampleNumber { get; set; }

   public ModConfig()
   {
      this.ExampleBoolean = true;
      this.ExampleNumber = 5;
   }
}

Using the config file

To read the config.json (SMAPI will create it automatically):

  1. Create your config model.
  2. Access the config values in your ModEntry class:
    /// <summary>The main entry point for the mod.</summary>
    internal sealed class ModEntry : Mod
    {
        /*********
        ** Properties
        *********/
        /// <summary>The mod configuration from the player.</summary>
        private ModConfig Config;
    
    
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            this.Config = this.Helper.ReadConfig<ModConfig>();
            bool exampleBool = this.Config.ExampleBoolean;
        }
    }
    

That's it! When the player launches the game, SMAPI will create the config.json file automatically if it doesn't exist yet, using the default config options you provided in your model. If you need to save some changes, you can use this.Helper.WriteConfig(this.Config).

Note that ReadConfig will raise an exception if the user does not provide a valid JSON.

Keybind settings

Main article: Modding:Modder Guide/APIs/Input

You can use SMAPI's KeybindList in your model to let users configure keybinds. This automatically supports multi-key or alternative bindings (e.g., to support split-screen mode):

class ModConfig
{
   public KeybindList ToggleKey { get; set; } = KeybindList.Parse("LeftShift + F2, LeftTrigger");
}

The value is automatically written/parsed in the config.json file as a string:

{
   "ToggleKey": "LeftShift + F2, LeftTrigger"
}