This page takes you from an empty Cargo project to a program that reads the configuration OpenMW would use, adds a plugin to it, and saves the change where the OpenMW launcher would. It assumes OpenMW is installed on the machine you run it on.
Add the crate#
cargo add openmw-config
The crate needs Rust 1.88 or newer. It has no required dependencies: on Windows it also uses
windows-sys to find the Documents folder, and the optional luau feature adds
l3i, which builds Luau itself and needs clang and lld;
Embedding Luau covers that.
Load the configuration#
use openmw_config::{ConfigError, OpenMWConfiguration};
fn main() -> Result<(), ConfigError> {
let config = OpenMWConfiguration::from_env_or_user_config()?;
println!("Loaded from {}", config.root_config_file().display());
for entry in config.config_chain() {
println!(" read {}", entry.path().display());
}
for directory in config.data_directories_iter() {
println!("data {}", directory.parsed().display());
}
for plugin in config.content_files_iter() {
println!("content {}", plugin.value());
}
Ok(())
}
from_env_or_user_config() finds the configuration the way OpenMW does, and falls back to the
user’s own openmw.cfg when no root config is found, which is what a tool running outside
OpenMW’s directory usually needs. Loading explains the alternatives.
The data directories are resolved paths: tokens like ?userdata? replaced, relative paths
anchored to the file that named them. The content files are names, in load order.
Change it and save#
use openmw_config::{ConfigError, OpenMWConfiguration};
fn main() -> Result<(), ConfigError> {
let mut config = OpenMWConfiguration::from_env_or_user_config()?;
if !config.has_content_file("Better Balmora.esp") {
config.add_content_file("Better Balmora.esp")?;
}
config.save_user()
}
add_content_file appends the plugin to the end of the load order and attributes it to the user’s
config, the last file in the chain. save_user() writes that one file back, with every comment it
had, and leaves the rest of the chain untouched. The write goes to a temporary file first, so a
crash cannot leave a half-written openmw.cfg.
Next#
- Loading: pick the right constructor for your kind of tool.
- Config chains: what happens between the root config and the user’s.
- Editing and Saving and exporting: the rest of the read-change-write cycle, and its traps.
- Embedding Luau, if your program runs scripts.