Various documentation updates

This commit is contained in:
Oliver Hamlet
2021-09-24 22:04:21 +01:00
parent 3cee54de04
commit e87ba12516
3 changed files with 53 additions and 27 deletions
+3 -2
View File
@@ -11,5 +11,6 @@ thousands of Bash Tag suggestions.
This metadata that LOOT supplies is stored in its masterlist, which is
maintained by the LOOT team using information provided by mod authors and users.
Users can also add to and modify the metadata used by LOOT through the use of
userlist files. libloot provides a way for third-party developers to access
this metadata for use in their own programs.
userlist files. libloot provides all of LOOT's non-UI-related functionality, and
can be used by third-party developers to access this metadata for use in their
own programs.
+44 -22
View File
@@ -15,7 +15,10 @@ String Encoding
Language Codes
==============
All language strings in the API are codes of the form ``ll`` or ``ll_CC``, where ``ll`` is an ISO 639-1 language code and ``CC`` is an ISO 3166 country code. For example, the default language for metadata message content is English, identified by the code ``en``, and Brazilian Portuguese is ``pt_BR``.
All language strings in the API are codes of the form ``ll`` or ``ll_CC``, where
``ll`` is an ISO 639-1 language code and ``CC`` is an ISO 3166 country code. For
example, the default language for metadata message content is English,
identified by the code ``en``, and Brazilian Portuguese is ``pt_BR``.
Errors
======
@@ -26,45 +29,64 @@ All errors encountered are thrown as exceptions that inherit from
Metadata Files
==============
LOOT stores plugin metadata in YAML files. It distinguishes between *masterlist*
and *userlist* files: each game has a single masterlist, which is a public,
curated metadata store, and each LOOT user has a private userlist, which can
contain metadata added by the user. The two files use the same syntax, but
metadata in the userlist extends or replaces metadata sourced from the
masterlist.
LOOT stores plugin metadata in YAML files. It distinguishes between three types
of metadata file:
- *masterlist* files: each game has a single masterlist, which is a public,
curated metadata store
- *masterlist prelude* files: there is a single masterlist prelude, which is a
public store of common metadata templates that can be shared across all
masterlists
- *userlist* files: each game has a userlist, which is a private user-specific
metadata store containing metadata added by the LOOT user.
All three files use the same syntax, but the masterlist prelude file is used to
replace part of a masterlist file before it is parsed, and metadata in the
userlist extends or replaces metadata sourced from the masterlist.
LOOT's plugin metadata can be conditional, eg. a plugin may require a patch only
if another plugin is also present. The API's :cpp:func:`LoadLists` method parses
metadata files into memory, but does not evaluate these conditions, so the
loaded metadata may contain metadata that is invalid for the installed game that
the :cpp:class:`loot::DatabaseInterface` object being operated on was created for.
the :cpp:class:`loot::DatabaseInterface` object being operated on was created
for.
Caching
=======
All unevaluated metadata is cached between calls to :cpp:func:`LoadLists`.
The results of evaluating metadata conditions are cached between calls to :cpp:func:`LoadPlugins`, :cpp:func:`SortPlugins` and
:cpp:func:`GetGeneralMessages`.
Plugin content is cached between calls to :cpp:func:`LoadPlugins` and
:cpp:func:`SortPlugins`.
Load order is cached between calls to :cpp:func:`LoadPlugins`,
:cpp:func:`SortPlugins` and :cpp:func:`LoadCurrentLoadOrderState`.
Load order is cached between calls to :cpp:func:`LoadCurrentLoadOrderState`.
Performance
===========
Loading metadata lists is a relatively costly operation, as is updating the
masterlist (which involves loading it).
The following may involve filesystem access and reading/parsing or writing of
data from the filesystem:
Sorting plugins is expensive, as it involves loading all the content of all
the plugins, apart from the game's main master file, which is skipped as an
optimisation (it doesn't depend on anything else and is much bigger than any
other plugin, so is unnecessary and slow to load).
- Any function that takes a ``std::filesystem::path``
- :cpp:any:`GameInterface::IsValidPlugin()`
- :cpp:any:`GameInterface::LoadPlugins()`
- :cpp:any:`GameInterface::LoadCurrentLoadOrderState()`
- :cpp:any:`GameInterface::SetLoadOrder()`
Getting plugin metadata once loaded is cheap, as is getting a masterlist's
revision.
Evaluating conditions may also involve filesystem read access.
Loading the current load order state is relatively cheap and can take < 1 ms
depending on hardware and the size of the load order, but involves filesystem
access and should not be done more often than necessary to avoid a performance
impact.
:cpp:any:`UpdateFile()` may involve network communication if given the URL of a
remote server.
:cpp:any:`GameInterface::SortPlugins()` is expensive, as it involves loading
all the content of all the plugins, apart from the game's main master file, which is skipped as an optimisation (it doesn't depend on anything else and is much bigger than any other plugin, so is unnecessary and slow to load).
:cpp:any:`DatabaseInterface::GetGroupsPath()` involves building a graph of all defined groups and
then using it to search for the shortest path between the two given groups,
which may be relatively slow given a sufficiently large and/or complex set of
group definitions.
All other API functions should be relatively fast.
+6 -3
View File
@@ -53,6 +53,10 @@ the group-derived plugin to the plugin would cause a cycle, and if not the edge
is recorded. Once all potential edges have been checked, the recorded edges are
added to the graph.
At this point the plugin graph is checked for cycles, and an error is thrown if
any are encountered, so that metadata (or indeed plugin data) that cause them
can be corrected.
Plugin overlap edges are then added. Two plugins overlap if they contain the
same record, i.e. if they both edit the same record or if one edits a record the
other plugin adds.
@@ -89,9 +93,8 @@ Topologically sort the plugin graph
===================================
Note that edges for explicit interdependencies are the only edges allowed to
create cycles: this is because the first step of this stage is to check the
plugin graph for cycles, and throw an error if any are encountered, so that
metadata (or indeed plugin data) that cause them can be corrected.
create cycles. However, the graph is again checked for cycles to guard against
potential logic bugs, and if a cycle is encountered an error is thrown.
Once the graph is confirmed to be cycle-free, a topological sort is performed on
the graph, outputting a list of plugins in their newly-sorted load order.