pub struct OpenMWConfiguration { /* private fields */ }Expand description
A fully-resolved OpenMW configuration chain.
Constructed by walking the config= chain starting from a root openmw.cfg, accumulating
every setting from every file into a flat list. The list preserves source attribution and
comments so that save_user can write back only the user-owned entries,
and Display can reproduce a valid, comment-preserving openmw.cfg.
Implementations§
Source§impl OpenMWConfiguration
impl OpenMWConfiguration
Sourcepub fn content_file_count(&self) -> usize
pub fn content_file_count(&self) -> usize
How many content= entries there are.
Sourcepub fn groundcover_file_count(&self) -> usize
pub fn groundcover_file_count(&self) -> usize
How many groundcover= entries there are.
Sourcepub fn archive_file_count(&self) -> usize
pub fn archive_file_count(&self) -> usize
How many fallback-archive= entries there are.
Sourcepub fn data_directory_count(&self) -> usize
pub fn data_directory_count(&self) -> usize
How many data= entries there are, the injected ones included.
Sourcepub fn sub_config_count(&self) -> usize
pub fn sub_config_count(&self) -> usize
How many config= entries remain in the effective chain.
Sourcepub fn generic_setting_count(&self) -> usize
pub fn generic_setting_count(&self) -> usize
How many preserved generic key=value entries there are.
Sourcepub fn game_setting_count(&self) -> usize
pub fn game_setting_count(&self) -> usize
How many distinct fallback= keys there are (what Self::game_settings yields).
Sourcepub fn from_env() -> Result<Self, ConfigError>
pub fn from_env() -> Result<Self, ConfigError>
§Errors
Returns ConfigError if the path from the environment variable is invalid or if config loading fails.
Discovery order matches OpenMW root config startup semantics:
OPENMW_CONFIG, an explicitopenmw.cfgfile path.OPENMW_CONFIG_DIR, a path list of directories containingopenmw.cfg.- Executable-adjacent
openmw.cfg. - Platform global config
openmw.cfg.
This deliberately does not fall back to Self::new(None). User config is loaded only if
the discovered root config references it, usually through config="?userconfig?".
§Example
use openmw_config::OpenMWConfiguration;
let config = OpenMWConfiguration::from_env()?;Sourcepub fn from_env_or_user_config() -> Result<Self, ConfigError>
pub fn from_env_or_user_config() -> Result<Self, ConfigError>
Loads an OpenMW configuration using environment/root discovery with a user-config fallback.
This is the discovery mode external tools normally want:
- Honor
Self::from_envsemantics, includingOPENMW_CONFIG,OPENMW_CONFIG_DIR, executable-adjacent root config, and platform global root config. - If strict root discovery finds no root config, fall back to the default user
openmw.cfg(?userconfig?/openmw.cfg).
Explicit environment errors are still errors. This method only adds a fallback for the “no local/global root config exists” case.
§Errors
Returns ConfigError if config loading fails or if no root/user config exists.
Sourcepub fn new(path: Option<PathBuf>) -> Result<Self, ConfigError>
pub fn new(path: Option<PathBuf>) -> Result<Self, ConfigError>
Loading creates the user config directory, Self::user_config_path, when it is
missing, as OpenMW’s engine does at every start; it writes no openmw.cfg there.
§Errors
Returns ConfigError if the path does not exist, is not a valid config, or if loading the config chain fails.
Returns ConfigError::NotWritable if the user config directory is missing and cannot
be created, where OpenMW stops with a fatal error.
§Example
use std::path::PathBuf;
use openmw_config::OpenMWConfiguration;
// Platform/user config default (?userconfig?/openmw.cfg), not OpenMW root discovery.
let config = OpenMWConfiguration::new(None)?;
// Specific directory or file path — both are accepted
let config = OpenMWConfiguration::new(Some(PathBuf::from("/home/user/.config/openmw")))?;Sourcepub fn new_empty(
user_config_dir: impl Into<PathBuf>,
) -> Result<Self, ConfigError>
pub fn new_empty( user_config_dir: impl Into<PathBuf>, ) -> Result<Self, ConfigError>
Creates an empty configuration rooted at user_config_dir without reading from disk.
The argument is a configuration directory, not an openmw.cfg file path. New settings are
attributed to user_config_dir/openmw.cfg, and save/export APIs treat that file as the user
config. The directory and file do not need to exist yet.
§Errors
Returns ConfigError::NotFileOrDirectory if user_config_dir is empty or is shaped like
an openmw.cfg file path. This keeps the directory-level API honest for future config-family
files such as settings.cfg and shaders.yaml.
Sourcepub fn load_optional(path: impl Into<PathBuf>) -> Result<Self, ConfigError>
pub fn load_optional(path: impl Into<PathBuf>) -> Result<Self, ConfigError>
Loads a configuration if it exists, otherwise creates an empty configuration at the same config context.
Existing paths behave exactly like Self::new. A missing openmw.cfg file path starts an
empty config from its parent directory; a missing directory path starts an empty config from
that directory. No input file is created unless a later save call writes one.
§Errors
Returns ConfigError for empty paths, invalid existing inputs, or load failures from
existing configs.
Sourcepub fn root_config_file(&self) -> &Path
pub fn root_config_file(&self) -> &Path
Path to the configuration file which is the root of the configuration chain
For Self::from_env, this is the root discovered by OpenMW startup semantics: explicit
environment override, executable-adjacent openmw.cfg, or platform global config. It is not
necessarily the user config; package installs usually load the user config through a root
config="?userconfig?" entry.
Typically, this will be whatever is defined in the Paths documentation for the appropriate platform:
https://openmw.readthedocs.io/en/latest/reference/modding/paths.html#configuration-files-and-log-files
Sourcepub fn root_config_dir(&self) -> PathBuf
pub fn root_config_dir(&self) -> PathBuf
Same as root_config_file, but returns the directory it’s in.
Useful for reading other configuration files, or if assuming openmw.cfg
Is always called openmw.cfg (which it should be)
§Panics
Panics if the root config path has no parent directory (i.e. it is a filesystem root).
pub fn is_user_config(&self) -> bool
Sourcepub fn user_config(self) -> Result<Self, ConfigError>
pub fn user_config(self) -> Result<Self, ConfigError>
The user’s config on its own, loaded from Self::user_config_path as
Self::load_optional loads: empty and rooted there when its openmw.cfg does not
exist yet, as on a fresh install. self when it already starts there.
§Errors
Returns ConfigError if the user config path cannot be loaded.
Sourcepub fn user_config_ref(&self) -> Result<Self, ConfigError>
pub fn user_config_ref(&self) -> Result<Self, ConfigError>
Self::user_config without consuming self: a clone when it already starts at the
user’s config.
§Errors
Returns ConfigError if the user config path cannot be loaded.
Sourcepub fn user_config_path(&self) -> PathBuf
pub fn user_config_path(&self) -> PathBuf
The directory of the user’s openmw.cfg: the last directory of the chain, or the root’s
when nothing chained. That is the file OpenMW and its launcher write, and the one
Self::save_user writes; Self::user_config loads it on its own.
A config= directory without an openmw.cfg counts: readConfiguration adds every
directory it reaches to its active config paths, loaded or not. So on a fresh install,
where the root’s config="?userconfig?" names a directory with no openmw.cfg yet, this is
that directory. Loading creates it, as OpenMW’s engine does, and Self::save_user
writes its openmw.cfg.
config= entries load depth first, as OpenMW’s readConfiguration walks them: a file’s
first config= and every file that one names load before its second. A root naming a
then b, where a names c, loads root, a, c, b, and b is the user’s.
OpenMW’s paths documentation describes that example level by level (root, a, b,
c); this crate does what OpenMW’s code does.
A replace=config in a file after the root drops the configs loaded before it except the
root, as OpenMW does; the chain carries on through every config= still to load.
See https://openmw.readthedocs.io/en/latest/reference/modding/paths.html#configuration-sources for the configuration sources.
pub fn userdata(&self) -> Option<&DirectorySetting>
pub fn set_userdata(&mut self, new: Option<DirectorySetting>)
pub fn resources(&self) -> Option<&DirectorySetting>
pub fn set_resources(&mut self, new: Option<DirectorySetting>)
pub fn data_local(&self) -> Option<&DirectorySetting>
pub fn set_data_local(&mut self, new: Option<DirectorySetting>)
pub fn encoding(&self) -> Option<&EncodingSetting>
pub fn set_encoding(&mut self, new: Option<EncodingSetting>)
Sourcepub fn set_data_local_path(&mut self, path: impl AsRef<Path>)
pub fn set_data_local_path(&mut self, path: impl AsRef<Path>)
Sets the singleton data-local= directory to a path attributed to the user config: the user
config’s definition is replaced when it is the last one, and a parent’s stays, followed
by the new one.
The value is parsed through DirectorySetting so quote, token, and relative-path handling
remains centralized.
Sourcepub fn set_resources_path(&mut self, path: impl AsRef<Path>)
pub fn set_resources_path(&mut self, path: impl AsRef<Path>)
Sets the singleton resources= directory to a path attributed to the user config: the user
config’s definition is replaced when it is the last one, and a parent’s stays, followed
by the new one.
The value is parsed through DirectorySetting so quote, token, and relative-path handling
remains centralized.
Sourcepub fn set_user_data_path(&mut self, path: impl AsRef<Path>)
pub fn set_user_data_path(&mut self, path: impl AsRef<Path>)
Sets the singleton user-data= directory to a path attributed to the user config: the user
config’s definition is replaced when it is the last one, and a parent’s stays, followed
by the new one.
The cfg key is user-data; ?userdata? is only a token. There is no userdata= key here.
Sourcepub fn clear_data_local(&mut self)
pub fn clear_data_local(&mut self)
Removes the last data-local= definition, which lets an earlier one, such as a parent’s,
take effect. Self::save_user persists removing the user config’s own; a parent’s can
only be removed from its file, with Self::save_subconfig.
Sourcepub fn clear_resources(&mut self)
pub fn clear_resources(&mut self)
Removes the last resources= definition, which lets an earlier one, such as a parent’s,
take effect. Self::save_user persists removing the user config’s own; a parent’s can
only be removed from its file, with Self::save_subconfig.
Sourcepub fn clear_user_data(&mut self)
pub fn clear_user_data(&mut self)
Removes the last user-data= definition, which lets an earlier one, such as a parent’s,
take effect. Self::save_user persists removing the user config’s own; a parent’s can
only be removed from its file, with Self::save_subconfig.
Sourcepub fn content_files_iter(&self) -> impl Iterator<Item = &FileSetting>
pub fn content_files_iter(&self) -> impl Iterator<Item = &FileSetting>
Content files are the actual mods or plugins which are created by either OpenCS or Bethesda’s construction set
These entries only refer to the names and ordering of content files.
vfstool-lib should be used to derive paths
Sourcepub fn has_content_file(&self, file_name: &str) -> bool
pub fn has_content_file(&self, file_name: &str) -> bool
Returns true if the named plugin is present in the content= list.
Sourcepub fn has_groundcover_file(&self, file_name: &str) -> bool
pub fn has_groundcover_file(&self, file_name: &str) -> bool
Returns true if the named plugin is present in the groundcover= list.
Sourcepub fn has_archive_file(&self, file_name: &str) -> bool
pub fn has_archive_file(&self, file_name: &str) -> bool
Returns true if the named archive is present in the fallback-archive= list.
Sourcepub fn has_data_dir(&self, file_name: &str) -> bool
pub fn has_data_dir(&self, file_name: &str) -> bool
Returns true if the given path is present in the data= list.
Both / and \ are normalised to the platform separator before comparison,
so the query does not need to use a specific separator style.
Sourcepub fn add_content_file(
&mut self,
content_file: &str,
) -> Result<(), ConfigError>
pub fn add_content_file( &mut self, content_file: &str, ) -> Result<(), ConfigError>
§Errors
Returns ConfigError::CannotAddContentFile if the file is already present in the config.
Sourcepub fn groundcover_iter(&self) -> impl Iterator<Item = &FileSetting>
pub fn groundcover_iter(&self) -> impl Iterator<Item = &FileSetting>
Iterates all groundcover= entries in definition order.
Sourcepub fn add_groundcover_file(
&mut self,
content_file: &str,
) -> Result<(), ConfigError>
pub fn add_groundcover_file( &mut self, content_file: &str, ) -> Result<(), ConfigError>
§Errors
Returns ConfigError::CannotAddGroundcoverFile if the file is already present in the config.
Sourcepub fn remove_content_file(&mut self, file_name: &str)
pub fn remove_content_file(&mut self, file_name: &str)
Removes all content= entries matching file_name.
Removing an entry a parent config defined makes the user config replace the content
list: save_user then writes replace=content and every remaining entry, the parents’
included, so the removal survives a reload. The remaining entries stay attributed to
the files that define them, so saving one of those with
save_subconfig writes them back there.
Sourcepub fn remove_groundcover_file(&mut self, file_name: &str)
pub fn remove_groundcover_file(&mut self, file_name: &str)
Removes all groundcover= entries matching file_name; removing a parent’s makes the
user config replace the list as in Self::remove_content_file (replace=groundcover).
Sourcepub fn remove_archive_file(&mut self, file_name: &str)
pub fn remove_archive_file(&mut self, file_name: &str)
Removes all fallback-archive= entries matching file_name; removing a parent’s makes
the user config replace the list as in Self::remove_content_file
(replace=fallback-archive).
Sourcepub fn remove_data_directory(&mut self, data_dir: &PathBuf)
pub fn remove_data_directory(&mut self, data_dir: &PathBuf)
Removes any data= entry whose resolved path or original string matches data_dir;
removing a parent’s makes the user config replace the list as in
Self::remove_content_file (replace=data). The resources/vfs and data-local
directories are no data= entries: they go when their settings are cleared.
Sourcepub fn add_data_directory(&mut self, dir: &Path)
pub fn add_data_directory(&mut self, dir: &Path)
Appends a data directory entry attributed to the user config. Does not check for duplicates.
Sourcepub fn add_archive_file(
&mut self,
archive_file: &str,
) -> Result<(), ConfigError>
pub fn add_archive_file( &mut self, archive_file: &str, ) -> Result<(), ConfigError>
§Errors
Returns ConfigError::CannotAddArchiveFile if the archive is already present in the config.
Sourcepub fn fallback_archives_iter(&self) -> impl Iterator<Item = &FileSetting>
pub fn fallback_archives_iter(&self) -> impl Iterator<Item = &FileSetting>
Iterates all fallback-archive= entries in definition order.
Sourcepub fn set_content_files(&mut self, plugins: Option<Vec<String>>)
pub fn set_content_files(&mut self, plugins: Option<Vec<String>>)
Replaces all content= entries with plugins, or clears them if None.
Entries are attributed to the user config path. No duplicate checking is performed.
When a parent config defined any of the old entries, save_user writes a
replace=content line ahead of the new ones, so a reload yields exactly this list.
Sourcepub fn set_fallback_archives(&mut self, archives: Option<Vec<String>>)
pub fn set_fallback_archives(&mut self, archives: Option<Vec<String>>)
Replaces all fallback-archive= entries with archives, or clears them if None.
Entries are attributed to the user config path. No duplicate checking is performed.
Parent-defined entries are replaced through replace=fallback-archive as in
Self::set_content_files.
Sourcepub fn generic_settings_iter(&self) -> impl Iterator<Item = &GenericSetting>
pub fn generic_settings_iter(&self) -> impl Iterator<Item = &GenericSetting>
Iterates all preserved generic key=value entries in definition order.
Sourcepub fn set_generic_settings(&mut self, key: &str, values: Option<Vec<String>>)
pub fn set_generic_settings(&mut self, key: &str, values: Option<Vec<String>>)
Replaces all preserved generic key=value entries with values, or clears them if None.
Entries are attributed to the user config path. No duplicate checking is performed.
Parent-defined entries are replaced through replace=<key> as in
Self::set_content_files; loading honours replace= for any key.
Sourcepub fn add_generic_setting(&mut self, key: &str, value: &str)
pub fn add_generic_setting(&mut self, key: &str, value: &str)
Appends a preserved generic key=value entry attributed to the user config.
Sourcepub fn settings_matching<'a, P>(
&'a self,
predicate: P,
) -> impl Iterator<Item = &'a SettingValue>
pub fn settings_matching<'a, P>( &'a self, predicate: P, ) -> impl Iterator<Item = &'a SettingValue>
Iterates all settings for which predicate returns true.
Sourcepub fn clear_matching<P>(&mut self, predicate: P)
pub fn clear_matching<P>(&mut self, predicate: P)
Removes all settings for which predicate returns true.
Sourcepub fn set_data_directories(&mut self, dirs: Option<Vec<PathBuf>>)
pub fn set_data_directories(&mut self, dirs: Option<Vec<PathBuf>>)
Replaces all data= entries with dirs, or clears them if None. The resources/vfs
and data-local directories stay first and last, as they follow their own settings.
Entries are attributed to the user config path. No duplicate checking is performed.
Parent-defined entries are replaced through replace=data as in
Self::set_content_files.
Sourcepub fn set_game_setting(
&mut self,
base_value: &str,
config_path: Option<PathBuf>,
comment: &mut String,
) -> Result<(), ConfigError>
pub fn set_game_setting( &mut self, base_value: &str, config_path: Option<PathBuf>, comment: &mut String, ) -> Result<(), ConfigError>
Given a string resembling a fallback= entry’s value, as it would exist in openmw.cfg, Add it to the settings map. This process must be non-destructive
comment is the text written above the entry, in openmw.cfg comment form: every line
that is not blank and does not already start with # gets a # prefix, and the whole
comment ends with a newline, so "my note" serializes as # my note\nfallback=.... It is
consumed (left empty), as the parser’s queued comments are.
§Errors
Returns ConfigError if base_value cannot be parsed as a valid game setting.
Sourcepub fn set_game_settings(
&mut self,
settings: Option<Vec<String>>,
) -> Result<(), ConfigError>
pub fn set_game_settings( &mut self, settings: Option<Vec<String>>, ) -> Result<(), ConfigError>
Replaces all fallback= entries with settings, or clears them if None.
Each string must be in Key,Value format — the same as it would appear after the = in
an openmw.cfg fallback= line. Parent-defined entries are replaced through
replace=fallback as in Self::set_content_files.
§Errors
Returns ConfigError if any entry in settings cannot be parsed as a valid game
setting; the old entries are then cleared and none of the new ones added.
Sourcepub fn sub_configs(&self) -> impl Iterator<Item = &DirectorySetting>
pub fn sub_configs(&self) -> impl Iterator<Item = &DirectorySetting>
Iterates the config= entries of the chain, file by file in the order the files loaded,
each file’s in its own order. An entry naming a directory without an openmw.cfg is one:
OpenMW keeps that directory in the chain. The chain loads depth first, so the last entry
here need not be the user’s config: Self::user_config_path is.
An entry naming a config a replace=config dropped is left out, so
Self::save_subconfig cannot write over that file.
Sourcepub fn config_chain(&self) -> impl Iterator<Item = &ConfigChainEntry>
pub fn config_chain(&self) -> impl Iterator<Item = &ConfigChainEntry>
Returns the observed configuration-chain traversal in the order the loader tried each
file: the root, then depth first through the config= entries, as OpenMW walks them.
Includes successfully loaded config files and config= targets that were skipped
because no openmw.cfg exists in that directory.
Sourcepub fn game_settings(&self) -> impl Iterator<Item = &GameSettingType>
pub fn game_settings(&self) -> impl Iterator<Item = &GameSettingType>
Fallback entries are k/v pairs baked into the value side of k/v pairs in fallback= entries of openmw.cfg.
They are used to express settings which are defined in Morrowind.ini for things such as:
weather, lighting behaviors, UI colors, and levelup messages.
Returns each key exactly once — when a key appears multiple times in the config chain, the
last-defined value wins. Keys come in reverse order of their effective definitions, most
recently defined first, so the user config’s settings lead: A,1 B,2 C,3 A,4 yields
A=4, C=3, B=2.
§Example
use openmw_config::OpenMWConfiguration;
let config = OpenMWConfiguration::new(None)?;
for setting in config.game_settings() {
println!("{}={}", setting.key(), setting.value());
}Sourcepub fn get_game_setting(&self, key: &str) -> Option<&GameSettingType>
pub fn get_game_setting(&self, key: &str) -> Option<&GameSettingType>
Retrieves a gamesetting according to its name.
This would be whatever text comes after the equals sign = and before the first comma ,
Case-sensitive!
Sourcepub fn data_directories_iter(&self) -> impl Iterator<Item = &DirectorySetting>
pub fn data_directories_iter(&self) -> impl Iterator<Item = &DirectorySetting>
Data directories are the bulk of an OpenMW Configuration’s contents,
Composing the list of files from which a VFS is constructed.
For a VFS implementation, see: https://github.com/magicaldave/vfstool/tree/main/vfstool_lib
Calling this function will give the post-parsed versions of directories defined by an openmw.cfg,
So the real ones may easily be iterated and loaded.
There is not actually validation anywhere in the crate that DirectorySettings refer to a directory which actually exists.
This is according to the openmw.cfg specification and doesn’t technically break anything but should be considered when using these paths.
Sourcepub fn to_resolved_string(&self) -> String
pub fn to_resolved_string(&self) -> String
Serializes the fully-composed configuration as a relocated, flattened openmw.cfg.
Directory-valued settings (data=, data-local=, resources=, and user-data=) are
emitted from their resolved paths, not their original token or relative spelling. Chain
control entries such as config= and replace= are excluded because this output is already
the composed result; reloading the chain from the flattened file would be doing the work
twice, and probably differently. The data= entries loading injects for data-local= and
resources= are also omitted.
Use the Display implementation for preservation-oriented serialization instead.
Sourcepub fn save_to_path(&self, path: impl AsRef<Path>) -> Result<(), ConfigError>
pub fn save_to_path(&self, path: impl AsRef<Path>) -> Result<(), ConfigError>
Writes the full composite configuration to an arbitrary path.
This is intended for importer-style output where the exact destination is supplied by the caller rather than inferred from the loaded config chain.
§Errors
Returns ConfigError::NotWritable if the destination directory is not writable.
Returns ConfigError::Io if writing the file fails.
Sourcepub fn save_resolved_to_path(
&self,
path: impl AsRef<Path>,
) -> Result<(), ConfigError>
pub fn save_resolved_to_path( &self, path: impl AsRef<Path>, ) -> Result<(), ConfigError>
Writes Self::to_resolved_string to an arbitrary path using atomic replace semantics.
This is the relocation-safe export API for importers and preview/output tools. It omits
config= and replace= chain-control entries and writes directory-valued settings using
resolved paths so moving the output file does not change what those paths mean.
§Errors
Returns ConfigError::NotWritable if the destination directory is not writable.
Returns ConfigError::Io if writing the file fails.
Sourcepub fn save_user(&self) -> Result<(), ConfigError>
pub fn save_user(&self) -> Result<(), ConfigError>
Saves the currently-defined user openmw.cfg configuration.
Only settings whose source is the user config file are written; parent configs are never
touched. When a set_* or remove_* method replaced a list a parent contributed to, or
removed a parent’s entry from one, the user config replaces that list: a replace= line
followed by the entries the parents still contribute, then its own. So what this writes
loads back as what was in memory.
On a fresh install the user’s openmw.cfg does not exist yet; this writes it, as
OpenMW’s launcher does when it first saves, and creates its directory again if it has
gone since loading created it.
§Errors
Returns ConfigError::NotWritable if the target path is not writable.
Returns ConfigError::Io if writing the file fails.
Sourcepub fn save_subconfig(&self, target_dir: &Path) -> Result<(), ConfigError>
pub fn save_subconfig(&self, target_dir: &Path) -> Result<(), ConfigError>
Saves the openmw.cfg belonging to a loaded sub-configuration.
target_dir must be the directory of a config= entry already present in the loaded
chain. This method refuses to write to arbitrary paths to prevent accidental overwrites.
The file gets the settings attributed to it, as Self::save_user writes the user’s.
§Errors
Returns ConfigError::SubconfigNotLoaded if target_dir is not part of the chain.
Returns ConfigError::NotWritable if the target path is not writable.
Returns ConfigError::Io if writing the file fails.
Trait Implementations§
Source§impl Clone for OpenMWConfiguration
impl Clone for OpenMWConfiguration
Source§impl Debug for OpenMWConfiguration
impl Debug for OpenMWConfiguration
Source§impl Default for OpenMWConfiguration
impl Default for OpenMWConfiguration
Source§impl Display for OpenMWConfiguration
Preservation-oriented openmw.cfg serialization for the composed configuration.
impl Display for OpenMWConfiguration
Preservation-oriented openmw.cfg serialization for the composed configuration.
Directory-valued settings use their original text so user-authored relative paths, tokens, and
quoting survive round-trips. That makes this suitable for preservation-style output and for the
internals of OpenMWConfiguration::save_user / OpenMWConfiguration::save_subconfig. It is
not relocation-safe flattened export: writing this string to a different directory can change the
meaning of relative paths. Use OpenMWConfiguration::to_resolved_string or
OpenMWConfiguration::save_resolved_to_path for importer/export output.
The data= entries loading injects for data-local= and resources= are omitted. Comments and
replace= entries are preserved. The comments that ended a file stay after that file’s
settings, including those added since loading.