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.
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 name
s.
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:
.cfg
file contains at least one node — these are “top-level” nodes, which require special treatment in MM.{
, possibly with newlines, spaces, or comments in-between. Everything afterward goes inside the node, until a closing brace }
or the end of the file is encountered.
RESOURCE {}
atmosphereCurve {}
=
, followed by another string (the value). It ends at either a newline or a comment (//
).
name = ModuleEnginesFX
mass = 3.5
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
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
}
}
}