3458 Commits
Author SHA1 Message Date
Oliver Hamlet 3a070420c8 Update version and changelog for v0.19.2 release 0.19.2 2023-01-13 21:27:03 +00:00
Oliver Hamlet 2c0538765b Add tests for PluginGraph::addHardcodedPluginEdges() 2023-01-13 21:27:03 +00:00
Oliver Hamlet 227ec847c8 Reintroduce validation of specific and hardcoded edges
So that any data or metadata contradicting master flags will cause
a cyclic interaction error as they did before the plugin graph was split
in 232202c17e.
2023-01-13 21:27:02 +00:00
Oliver Hamlet 1b0ed35a7f Rewrite PluginSortTest group tests and add many more
Most of the existing tests ave been rewritten as PluginGraphTest tests,
because the tests can be simpler, faster, clearer and more tightly
scoped to the functionality that's actually being tested.
2023-01-13 21:27:02 +00:00
Oliver Hamlet 9e06db4d16 Fix avoidance of group cycles involving user metadata
This bug was introduced in 53e2dbba1f,
and affects libloot v0.19.1.
2023-01-13 17:20:14 +00:00
Oliver Hamlet 6c1d7dc57f Update version and changelog for v0.19.1 release 0.19.1 2023-01-09 19:13:26 +00:00
Oliver Hamlet 58df21f11c Revert back to using lexicographical vertex order
For vertices in the plugin graph. This is so that the group and overlap
edges are evaluated in an order that does not depend on the current load
order. Tie-breaking still uses the current load order.

This is necessary because if the group and overlap edges that get added
depend on the current load order, sorting and applying changes the
current load order, so sorting again may give different results even
even though no plugin data or metadata has changed.
2023-01-09 19:00:41 +00:00
Oliver Hamlet 53e2dbba1f Refactor SortPlugins() for ease of testing
Expose a new overload that doesn't depend on Game and call that
from the existing SortPlugins() function.
2023-01-09 18:54:24 +00:00
Oliver Hamlet 938d5bce57 Update version and changelog for v0.19.0 release 0.19.0 2023-01-07 19:21:35 +00:00
Oliver Hamlet 614a8d306c Add missing doxygen doc comment 2023-01-07 19:21:34 +00:00
Oliver Hamlet aaf05a6460 Find predecessor group plugins on demand
Rather than storing them in PluginSortingData, which is now immutable.

This also means the predecessor groups plugins map can use vertices
instead of plugin names, which is a
little simpler.
2023-01-06 22:30:12 +00:00
Oliver Hamlet a82f9a8f99 Return vertex from PluginGraph::AddVertex() 2023-01-06 22:20:37 +00:00
Oliver Hamlet 1abba782f0 Clean up some includes 2023-01-06 22:20:36 +00:00
Oliver Hamlet 7a8f5da170 Check plugin validity in parallel
This is about 30% faster.
2023-01-06 22:20:36 +00:00
Oliver Hamlet 8c40db89fd Use C++17 parallel algorithms during plugin loading
This requires linking to the TBB library on Linux, where libstdc++
and libc++ don't provide an implementation.
2023-01-06 22:20:36 +00:00
Oliver Hamlet 055161ef0e Update CI Linux builds to use GCC 10
GCC 8 doesn't support C++17's parallel algorithms, which I'd like to
use, and GCC 10 is the newest major version available from Ubuntu
20.04's repositories.

This commit removes a Linux-only std::filesystem::path constructor test,
which fails due to a thrown exception when compiled with GCC 10. The
failure isn't important, because libloot avoids that particular
constructor: in a sense an exception is a bit better because it would
make any usage more obvious.
2023-01-06 22:20:35 +00:00
Oliver Hamlet 43ee1549d2 Distinguish between overlap edge types
By providing different edge types for record overlap and asset overlap.
2023-01-06 22:20:35 +00:00
Oliver Hamlet 92c71cd352 Distinguish group edges by data source
If a group edge exists due to the presence of some user metadata,
distinguish that from when the edge exists only due to masterlist
metadata.

The logic for detecting when a path between two groups involves user
metadata gives results that are stable but that do not consistently
paths that only consist of masterlist metadata. If there are multiple
paths between two groups and some involve user metadata, the same path
will be picked every time, but the path picked depends on the structure
of the groups graph.

In practice this shouldn't be much of a problem because the paths are
only exposed when there's a cycle, and in that case all paths between
the two groups need to be removed/broken anyway.
2023-01-06 22:20:35 +00:00
Oliver Hamlet 10a9ba60e2 Make UndefinedGroupError::GetGroupName() const
Also move the constructor and function definitions out of the header
where they're declared.
2023-01-06 22:20:34 +00:00
Oliver Hamlet 57b397aed6 Make CyclicInteractionError::GetCycle() const 2023-01-06 22:20:34 +00:00
Oliver Hamlet fbc503a363 Rename PluginInterface::DoFormIDsOverlap()
The use of FormIDs doesn't apply to Morrowind and it's really the
records that are significant - FormIDs are an implementation detail.
This also aligns with other use of records in names.
2023-01-06 22:20:34 +00:00
Oliver Hamlet 2c976f8848 Add GameInterface::GetActivePluginsFilePath()
This breaks ABI compatibility, but LOOT can use it to stop guessing
where the file is when it needs to display the path.
2023-01-06 22:20:34 +00:00
Oliver Hamlet ef2a34aa23 Minor optimisations to adding hardcoded edges
It only speeds up sorting by about 3% with my 1619 plugin load order,
but I think the logic is simpler despite all the iterators involved.
2023-01-06 22:20:33 +00:00
Oliver Hamlet 232202c17e Split plugin graph in two
All master-flagged plugins must load before all non-master-flaggeg
plugins, and this means that most of the edges added in the graph
(about 2/3rds in large load orders) are just enforcing this.

Having lots of edges negatively impacts the performance of checking for
paths, and adding overlap edges is O(n^2), so instead of having one
graph containing all plugins, create one graph for masters and another
for plugins, and sort them independently, then append the non-masters
order to the masters order.

This speeds up my 1619 plugin sort from 44s to 34s, and larger load
orders should see more benefit.

This does introduce some behavioural changes though:

- any requirement or load after metadata that tries to put a master
  after a non-master will now be ignored instead of causing a cyclic
  interaction error. A master-flagged plugin that has a
  non-master-flagged plugin will also no longer cause a cyclic
  interaction error, but that scenario is much less likely.
- The resulting load order may differ slightly. When tie-breaking finds
  a path that contradicts the old load order, it pins the positions of
  plugins in the path. However, the lack of master flag edges causes
  later edges to be added or skipped differently. This is all ultimately
  down to the order of edge iteration mattering during path discovery
  (since it stops at the first path discovered), so even though the two
  approaches result in graphs that enforce the same relationships
  between plugins at the point that tie-breaking starts, ties may be
  broken differently due to differences in the edges enforcing those
  relationships.
2023-01-06 22:20:31 +00:00
Oliver Hamlet ddf818ff51 Refactor adding plugin vertices to graph 2023-01-06 21:48:07 +00:00