diff --git a/include/loot/game_interface.h b/include/loot/game_interface.h index 89a49d9b..a9dc9385 100644 --- a/include/loot/game_interface.h +++ b/include/loot/game_interface.h @@ -118,7 +118,8 @@ public: * applied to the load order used by the game. This function does * not load or evaluate the masterlist or userlist. * @param plugins - * A vector of filenames of the plugins to sort. + * A vector of filenames of the plugins to sort, in their current + * load order. * @returns A vector of the given plugin filenames in their sorted load * order. */ diff --git a/src/api/game/game.cpp b/src/api/game/game.cpp index 534709be..5c0c4fe4 100644 --- a/src/api/game/game.cpp +++ b/src/api/game/game.cpp @@ -221,7 +221,7 @@ std::vector Game::SortPlugins( LoadPlugins(plugins, false); // Sort plugins into their load order. - return loot::SortPlugins(*this); + return loot::SortPlugins(*this, plugins); } void Game::LoadCurrentLoadOrderState() { diff --git a/src/api/sorting/plugin_graph.cpp b/src/api/sorting/plugin_graph.cpp index c8e06495..2a5abbc4 100644 --- a/src/api/sorting/plugin_graph.cpp +++ b/src/api/sorting/plugin_graph.cpp @@ -126,7 +126,9 @@ std::vector PluginGraph::TopologicalSort() const { std::map indexMap; auto vertexIndexMap = vertex_map_t(indexMap); size_t i = 0; - BGL_FORALL_VERTICES(v, graph_, RawPluginGraph) { put(vertexIndexMap, v, i++); } + BGL_FORALL_VERTICES(v, graph_, RawPluginGraph) { + put(vertexIndexMap, v, i++); + } list sortedVertices; auto logger = getLogger(); @@ -167,7 +169,8 @@ std::vector PluginGraph::TopologicalSort() const { return plugins; } -void PluginGraph::AddPluginVertices(Game& game) { +void PluginGraph::AddPluginVertices(Game& game, + const std::vector& loadOrder) { // The resolution of tie-breaks in the plugin graph may be dependent // on the order in which vertices are iterated over, as an earlier tie // break resolution may cause a potential later tie break to instead @@ -191,8 +194,6 @@ void PluginGraph::AddPluginVertices(Game& game) { // full plugin objects then sorting them. std::map> groupPlugins; - auto loadOrder = game.GetLoadOrder(); - auto loadedPlugins = game.GetCache()->GetPlugins(); for (const auto& plugin : loadedPlugins) { auto masterlistMetadata = @@ -282,14 +283,16 @@ void PluginGraph::CheckForCycles() const { std::map indexMap; auto vertexIndexMap = vertex_map_t(indexMap); size_t i = 0; - BGL_FORALL_VERTICES(v, graph_, RawPluginGraph) { put(vertexIndexMap, v, i++); } + BGL_FORALL_VERTICES(v, graph_, RawPluginGraph) { + put(vertexIndexMap, v, i++); + } boost::depth_first_search( graph_, visitor(CycleDetector()).vertex_index_map(vertexIndexMap)); } bool PluginGraph::EdgeCreatesCycle(const vertex_t& fromVertex, - const vertex_t& toVertex) { + const vertex_t& toVertex) { if (pathsCache_.count(GraphPath(toVertex, fromVertex)) != 0) { return true; } @@ -346,8 +349,8 @@ bool PluginGraph::EdgeCreatesCycle(const vertex_t& fromVertex, } void PluginGraph::AddEdge(const vertex_t& fromVertex, - const vertex_t& toVertex, - EdgeType edgeType) { + const vertex_t& toVertex, + EdgeType edgeType) { auto graphPath = GraphPath(fromVertex, toVertex); if (pathsCache_.count(graphPath) != 0) { @@ -357,9 +360,9 @@ void PluginGraph::AddEdge(const vertex_t& fromVertex, auto logger = getLogger(); if (logger) { logger->trace("Adding {} edge from \"{}\" to \"{}\".", - describeEdgeType(edgeType), - graph_[fromVertex].GetName(), - graph_[toVertex].GetName()); + describeEdgeType(edgeType), + graph_[fromVertex].GetName(), + graph_[toVertex].GetName()); } boost::add_edge(fromVertex, toVertex, edgeType, graph_); diff --git a/src/api/sorting/plugin_graph.h b/src/api/sorting/plugin_graph.h index 4eda2e17..f8c1f618 100644 --- a/src/api/sorting/plugin_graph.h +++ b/src/api/sorting/plugin_graph.h @@ -83,7 +83,7 @@ public: size_t CountVertices() const; void CheckForCycles() const; - void AddPluginVertices(Game& game); + void AddPluginVertices(Game& game, const std::vector& loadOrder); void AddSpecificEdges(); void AddHardcodedPluginEdges(Game& game); void AddGroupEdges(const std::unordered_set& groups); diff --git a/src/api/sorting/plugin_sort.cpp b/src/api/sorting/plugin_sort.cpp index 5a433112..ae27966f 100644 --- a/src/api/sorting/plugin_sort.cpp +++ b/src/api/sorting/plugin_sort.cpp @@ -28,10 +28,12 @@ #include "api/sorting/plugin_graph.h" namespace loot { -std::vector SortPlugins(Game& game) { +std::vector SortPlugins( + Game& game, + const std::vector& loadOrder) { PluginGraph graph; - graph.AddPluginVertices(game); + graph.AddPluginVertices(game, loadOrder); // If there aren't any vertices, exit early, because sorting assumes // there is at least one plugin. @@ -41,7 +43,7 @@ std::vector SortPlugins(Game& game) { auto logger = getLogger(); if (logger) { logger->info("Current load order: "); - for (const auto& plugin : game.GetLoadOrder()) { + for (const auto& plugin : loadOrder) { logger->info("\t\t{}", plugin); } } diff --git a/src/api/sorting/plugin_sort.h b/src/api/sorting/plugin_sort.h index a875e953..822ae55b 100644 --- a/src/api/sorting/plugin_sort.h +++ b/src/api/sorting/plugin_sort.h @@ -31,7 +31,8 @@ #include "api/game/game.h" namespace loot { -std::vector SortPlugins(Game& game); +std::vector SortPlugins(Game& game, + const std::vector& loadOrder); } #endif diff --git a/src/tests/api/internals/sorting/plugin_sort_test.h b/src/tests/api/internals/sorting/plugin_sort_test.h index a87875dc..590a414f 100644 --- a/src/tests/api/internals/sorting/plugin_sort_test.h +++ b/src/tests/api/internals/sorting/plugin_sort_test.h @@ -132,7 +132,7 @@ INSTANTIATE_TEST_CASE_P(, GameType::fo4)); TEST_P(PluginSortTest, sortingWithNoLoadedPluginsShouldReturnAnEmptyList) { - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_TRUE(sorted.empty()); } @@ -145,7 +145,7 @@ TEST_P(PluginSortTest, // Check stability by running the sort 100 times. for (int i = 0; i < 100; i++) { - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); ASSERT_EQ(expectedSortedOrder, sorted) << " for sort " << i; } } @@ -182,7 +182,7 @@ TEST_P(PluginSortTest, sortingShouldResolveGroupsAsTransitiveLoadAfterSets) { expectedSortedOrder.insert(expectedSortedOrder.begin() + 5, blankEsl); } - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -193,7 +193,7 @@ TEST_P(PluginSortTest, sortingShouldThrowIfAPluginHasAGroupThatDoesNotExist) { plugin.SetGroup("group1"); game_.GetDatabase()->SetPluginUserMetadata(plugin); - EXPECT_THROW(SortPlugins(game_), UndefinedGroupError); + EXPECT_THROW(SortPlugins(game_, game_.GetLoadOrder()), UndefinedGroupError); } TEST_P(PluginSortTest, @@ -225,7 +225,7 @@ TEST_P(PluginSortTest, expectedSortedOrder.insert(expectedSortedOrder.begin() + 3, blankEsl); } - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -269,7 +269,7 @@ TEST_P( expectedSortedOrder.insert(expectedSortedOrder.begin() + 5, blankEsl); } - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -309,7 +309,7 @@ TEST_P( expectedSortedOrder.insert(expectedSortedOrder.begin() + 3, masterFile); } - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -334,7 +334,7 @@ TEST_P( game_.GetDatabase()->SetPluginUserMetadata(plugin); try { - SortPlugins(game_); + SortPlugins(game_, game_.GetLoadOrder()); FAIL(); } catch (CyclicInteractionError &e) { ASSERT_EQ(3, e.GetCycle().size()); @@ -348,8 +348,9 @@ TEST_P( } } -TEST_P(PluginSortTest, - sortingShouldNotIgnoreIntermediatePluginsInAMultiGroupCycleIfTheEarlierPluginIsNotAMasterAndTheLaterIs) { +TEST_P( + PluginSortTest, + sortingShouldNotIgnoreIntermediatePluginsInAMultiGroupCycleIfTheEarlierPluginIsNotAMasterAndTheLaterIs) { ASSERT_NO_THROW(loadInstalledPlugins(game_, false)); GenerateMasterlist(); @@ -383,7 +384,7 @@ TEST_P(PluginSortTest, expectedSortedOrder.insert(expectedSortedOrder.begin() + 1, masterFile); } - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -421,7 +422,7 @@ TEST_P( expectedSortedOrder.insert(expectedSortedOrder.begin() + 2, blankEsl); } - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -453,7 +454,7 @@ TEST_P(PluginSortTest, expectedSortedOrder.insert(expectedSortedOrder.begin() + 5, blankEsl); } - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -485,7 +486,7 @@ TEST_P(PluginSortTest, expectedSortedOrder.insert(expectedSortedOrder.begin() + 5, blankEsl); } - std::vector sorted = SortPlugins(game_); + std::vector sorted = SortPlugins(game_, game_.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -516,7 +517,8 @@ TEST_P(PluginSortTest, blankDifferentPluginDependentEsp, }); - std::vector sorted = SortPlugins(newGame); + std::vector sorted = + SortPlugins(newGame, newGame.GetLoadOrder()); EXPECT_EQ(expectedSortedOrder, sorted); } @@ -526,7 +528,8 @@ TEST_P(PluginSortTest, sortingShouldThrowIfACyclicInteractionIsEncountered) { plugin.SetLoadAfterFiles({File(blankMasterDependentEsm)}); game_.GetDatabase()->SetPluginUserMetadata(plugin); - EXPECT_THROW(SortPlugins(game_), CyclicInteractionError); + EXPECT_THROW(SortPlugins(game_, game_.GetLoadOrder()), + CyclicInteractionError); } } }