1. Introduction

ModuleManager is a mini-language that allows mods to patch config nodes in a systematic way. While imperfect in a large number of ways, it is nonetheless exceedingly powerful — when used correctly. This guide seeks to provide a unified reference for the capabilities of ModuleManager, as well as noting common misconceptions and pitfalls.

Concepts

Config files, nodes, and keys

KSP stores configuration information using .cfg files containing config nodes, which can recursively contain nodes, as well as keys.

A node must have a type (PART, MODULE, atmosphereCurve, &c.). This type is relatively difficult to change and to work with in MM. Since a large number of nodes have a name key (notably, both parts and part modules), MM provides special facilities to access nodes via their names.

Keys, on the other hand, are strings which index values — note that keys need not be unique! Furthermore, values are stored as strings. As an example, to perform an arithmetic operation, MM will try to parse the value as a number, operate on it, and then convert the result back into a string.

Very roughly speaking, a ConfigNode can be thought of as:

class ConfigNode
{
    List<ConfigNode> nodes;
    List<KeyValuePair<string, string>> values;
    string nodeType;  // This field is actually called `name` in KSP.
}

The syntax accepted by KSP is “simple” — vaguely and approximately:

Patching config nodes

All of ModuleManager builds upon stock .cfg files — that is, MM patches must be valid config nodes that can be parsed by KSP (but happen to have special meaning to MM). Being forced to work within this rather constrained and ill-defined set of contents places restrictions on what syntax is possible.

Patches are top-level nodes that operate on existing top-level nodes (most commonly by modifying or duplicating an existing node). Once KSP loads all .cfg files into memory, MM finds and applies patches to the loaded config nodes (see Section 3).

TODO: config cache

2. Basic Usage

As with other .cfg files, patches must be placed in GameData to be loaded by KSP. A simple patch might create a modified version of a stock part:

// In `GameData/customVector.cfg`.
// For demonstration purposes only.

// Duplicate the stock part named SSME (the Vector engine).
+PART[SSME]
{
    // Rename it to something else.
    @name = customSSME
}

// Modify the newly duplicated part.
@PART[customSSME]
{
    // Increase its mass by 50%.
    @mass *= 1.5
    // Increase its cost by 2000 funds.
    @cost += 2000
    // Modify a module named ModuleEnginesFX.
    @MODULE[ModuleEnginesFX]
    {
        // Modify a PROPELLANT node named LiquidFuel.
        @PROPELLANT[LiquidFuel]
        {
            // Change the ratio of LiquidFuel consumed.
            @ratio = 1.0
        }

        // Add a new PROPELLANT node (thus, a new propellant).
        PROPELLANT
        {
            name = Monopropellant
            ratio = 0.1
        }
    }
}