tModLoader Modder's Guide to Config Files and Optional Features

gardenapple

Steampunker
Welcome!
Today I'd like to show you how to add your own Config/Options file to your tModLoader mod. Players will be able to edit that file to change your mod's behavior.

In this guide, I'll assume that you have at least very basic knowledge of how to make a tModLoader mod, and you already have a basic Mod class set up. You won't need too much actual C# knowledge to understand what's going on, or at least I hope so.

Now how is this useful? Why would I want an options file for a mod?

Imagine that you made a tweaks mod. It changes some vanilla features, such as HP of some bosses, or it may add a set bonus to some piece of armor, or add an alternative recipe for some frustratingly rare item. Some players might like that change, while others might feel like your mod is too cheaty or too "hardcode" for their taste. By allowing players to choose exactly what things they want or don't want in a mod, you can provide a more Sandbox-like experience for them. And Terraria is, after all, a Sandbox game, right?

One example of this is my mod Boss Expertise (yay for self-advertising!). It allows players to choose exactly what Boss tweaks they want (if they don't want tougher AI but they do want to get Treasure Bags in Normal Mode, they're welcome).

Now of course, not every mod needs a configuration file. If your mod is full of lore and carefully created content, where every item, enemy, NPC and boss matters, then letting players disable parts of the mod might be a bad idea. But really, it's up to you to decide.

...

Okay, so you've thought about this for a moment, and made your decision. If you do feel like you want an Options file in your mod, then let's begin!

Step 1: Simple JSON config file
Yes, we will be using JSON for this. There's two reasons for that.
  1. Firstly, the JSON format is simple yet very flexible. It can store booleans, integers, floats, text strings, arrays, all kinds of stuff! And it's rather simple for people to manually edit.
  2. Secondly, that's the easiest way of doing it in a tModLoader mod. Why? Because Terraria's codebase already has a neat way of working with JSON, and it's through the Preferences class! Re-Logic itself uses it to store the game's options and controls, and luckily we, mere mortals modders, have access to it, too! And t's really simple to use.
In this example we will make a mod that does two things:
  • It'll change Plantera's HP. The player will be able to set Plantera's max health to any number they want through the config file.
  • It'll add a recipe for 1 Dirt Block -> 1 Stone Block if the player enables it in the config.

(Note: once tModLoader implements ModOptions this guide WILL become obsolete. When that happens, I'll either rewrite the whole thing or make a completely new guide. Or I might not do anything. We'll see.)

Let's start with the actual configuration code itself. It should look somewhat like this:
Code:
using System;
using System.IO;
using Terraria;
using Terraria.IO;
using Terraria.ModLoader;

namespace ExampleMod
{
    public static class Config
    {
        public static bool StoneRecipe = true;
        public static int PlanteraHP = 30000;

        //The file will be stored in "Terraria/ModLoader/Mod Configs/Example Mod.json"
        static string ConfigPath = Path.Combine(Main.SavePath, "Mod Configs", "Example Mod.json");

        static Preferences Configuration = new Preferences(ConfigPath);

        public static void Load()
        {
            //Reading the config file
            bool success = ReadConfig();

            if(!success)
            {
                ErrorLogger.Log("Failed to read Example Mod's config file! Recreating config...");
                CreateConfig();
            }
        }

        //Returns "true" if the config file was found and successfully loaded.
        static bool ReadConfig()
        {
            if(Configuration.Load())
            {
                Configuration.Get("StoneRecipe", ref StoneRecipe);
                Configuration.Get("PlanteraHP", ref PlanteraHP);
                //We don't want Plantera to have negative HP :P
                if(PlanteraHP <= 0)
                   PlanteraHP = 1;
                return true;
            }
            return false;
        }

        //Creates a config file. This will only be called if the config file doesn't exist yet or it's invalid. 
        static void CreateConfig()
        {
            Configuration.Clear();
            Configuration.Put("StoneRecipe", StoneRecipe);
            Configuration.Put("PlanteraHP", PlanteraHP);
            Configuration.Save();
        }
    }
}
Don't forget to replace namespace ExampleMod with your mod's name!

You could put all of that code into your main mod class, but just for the sake of simplicity let's put it in a separate file called Config.cs. Then in our ExampleMod.cs we'll have something like this:
Code:
public override void Load()
{
   Config.Load();
}

To test this, simply Build+Reload, find your Terraria save folder, and go to "ModLoader/Mod Configs/Example Mod.json", and you should find something like this:
Code:
{
  "StoneRecipe": true,
  "PlanteraHP": 30000
}

Note: if you ever feel like your .json file is getting too long and hard to edit, you can always use multiple Preferences objects to split your options into multiple files.

Anyway, now that we have a (hopefully) working config file, we can put it to use!

Step 2: Doing stuff
If you have some C# programming knowledge, then you probably know how to make good use of this config file already. But, I want this tutorial to be helpful to both experienced modders and beginners. So I will show off some basic things you can do with this.

The code below will set Plantera's max health to Config.PlanteraHP, which will be a configurable value that players can change thanks to our Config class.
Code:
using System;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace ExampleMod
{
    public class PlanteraTweaks : GlobalNPC
    {
        public override void SetDefaults(NPC npc)
        {
            switch(npc.type)
            {
                case NPCID.Plantera:
                    npc.lifeMax = Config.PlanteraHP;
                    npc.life = Config.PlanteraHP;
                    break;
            }
        }
    }
}
Save this in a separate file called PlanteraTweaks.cs or something.

And this next bit of code will add the Dirt to Stone recipe that I've talked about earlier.
Code:
public override void AddRecipes()
{
   if(Config.StoneRecipe)
   {
      var recipe = new ModRecipe(this); //if you're using this inside a ModItem class, replace "this" with "mod".
      recipe.AddIngredient(ItemID.DirtBlock);
      recipe.SetResult(ItemID.StoneBlock);
      recipe.AddRecipe();
   }
}
Put that in your Mod class (don't forget to put using Terraria.ID; at the top!), and it should work.

So that's it! Hopefully this will inspire you to make mods with a better Sandbox feel!

As always, feedback and suggestions are appreciated. And if I screwed up the code somehow and melted your computer in the process, feel free to yell at me! I'll try to fix everything that I can.
 
Last edited:
Good, but what about multiplayer? You may need to use ModWorld.SendCustomData/ReceiveCustomData to sync the values from the server to the clients.
 
Good, but what about multiplayer? You may need to use ModWorld.SendCustomData/ReceiveCustomData to sync the values from the server to the clients.
You're right, I didn't think about that. I'm not sure if I should cover this here or in another guide though.
 
When mods have these kind of configurations, is there any way of changing those options aside from directly editing the .json files?
 
Back
Top Bottom