diff --git a/src/backend/game.cpp b/src/backend/game.cpp index 46ba275c..56f34e07 100644 --- a/src/backend/game.cpp +++ b/src/backend/game.cpp @@ -31,6 +31,7 @@ #include "streams.h" #include +#include using namespace std; @@ -572,19 +573,44 @@ namespace loot { } void Game::LoadPlugins(bool headersOnly) { - //Add all plugins in data folder not already in the hashset to the hashset, and load them. - for (fs::directory_iterator it(DataPath()); it != fs::directory_iterator(); ++it) { + boost::thread_group group; + size_t meanFileSize = 0; + unordered_map tempMap; + std::set skipPlugins; + //First calculate the mean plugin size. Store it temporarily in a map to reduce filesystem lookups and file size recalculation. + for (fs::directory_iterator it(this->DataPath()); it != fs::directory_iterator(); ++it) { if (fs::is_regular_file(it->status()) && IsPlugin(it->path().string())) { - const string filename = it->path().filename().string(); - if (plugins.find(filename) == plugins.end()) - plugins.insert(std::pair(filename, Plugin(filename))); + size_t fileSize = fs::file_size(it->path()); + meanFileSize += fileSize; + + tempMap.emplace(it->path().filename().string(), fileSize); } } + meanFileSize /= tempMap.size(); - for (auto &pluginPair: plugins) { - pluginPair.second = Plugin(*this, pluginPair.second.Name(), headersOnly); + //Now load plugins. + for (const auto &pluginPair : tempMap) { + + BOOST_LOG_TRIVIAL(info) << "Found plugin: " << pluginPair.first; + + auto plugin = plugins.emplace(pluginPair.first, Plugin(pluginPair.first)); + + if (pluginPair.second > meanFileSize) { + skipPlugins.insert(pluginPair.first); + group.create_thread([this, &plugin, headersOnly]() { + plugin.first->second = Plugin(*this, plugin.first->first, headersOnly); + }); + } } + group.create_thread([this, &skipPlugins, headersOnly]() { + for (auto &pluginPair : this->plugins) { + if (skipPlugins.find(pluginPair.first) == skipPlugins.end()) { + pluginPair.second = Plugin(*this, pluginPair.first, headersOnly); + } + } + }); + group.join_all(); } void Game::CreateLOOTGameFolder() { diff --git a/src/backend/game.h b/src/backend/game.h index 73384df0..e67e9b47 100644 --- a/src/backend/game.h +++ b/src/backend/game.h @@ -78,56 +78,6 @@ namespace loot { std::string revision; std::string date; }; - /* - class PluginCache { - - - bool IsActive(const std::string& plugin) const; - - void GetLoadOrder(std::list& loadOrder) const; - void SetLoadOrder(const std::list& loadOrder) const; //Modifies game load order, even though const. - - void RefreshActivePluginsList(); - void RedatePlugins(); //Change timestamps to match load order (Skyrim only). - void LoadPlugins(bool headersOnly); //Loads all installed plugins. - std::unordered_map plugins; //Map so that plugin data can be edited. - - std::unordered_set activePlugins; //Holds lowercased strings. - }; - */ - - // A couple of plugin loader classes for handling plugin loading in separate threads. - class PluginLoader { - public: - PluginLoader(Plugin& plugin, Game& game) : _plugin(plugin), _game(game) { - } - - void operator () () { - _plugin = Plugin(_game, _plugin.Name(), false); - } - - Plugin& _plugin; - Game& _game; - std::string _filename; - bool _b; - }; - - class PluginsLoader { - public: - PluginsLoader(std::list& plugins, Game& game) : _plugins(plugins), _game(game) {} - - void operator () () { - for (auto &plugin : _plugins) { - if (skipPlugins.find(plugin.Name()) == skipPlugins.end()) { - plugin = Plugin(_game, plugin.Name(), false); - } - } - } - - std::list& _plugins; - Game& _game; - std::set skipPlugins; - }; class Game { public: @@ -159,7 +109,6 @@ namespace loot { boost::filesystem::path UserlistPath() const; boost::filesystem::path ReportDataPath() const; -//TO BE REMOVED //Game plugin functions. bool IsActive(const std::string& plugin) const; @@ -173,12 +122,11 @@ namespace loot { //Caches for condition results, active plugins and CRCs. std::unordered_map conditionCache; //Holds lowercased strings. std::unordered_map crcCache; //Holds lowercased strings. -//END TO BE REMOVED //Plugin data and metadata lists. Masterlist masterlist; MetadataList userlist; - std::unordered_map plugins; //Map so that plugin data can be edited. TO BE REMOVED + std::unordered_map plugins; //Map so that plugin data can be edited. espm::Settings espm_settings; @@ -200,7 +148,7 @@ namespace loot { boost::filesystem::path gamePath; //Path to the game's folder. - std::unordered_set activePlugins; //Holds lowercased strings. TO BE REMOVED + std::unordered_set activePlugins; //Holds lowercased strings. //Creates directory in LOOT folder for LOOT's game-specific files. void CreateLOOTGameFolder(); diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 3f20668d..da23ae3e 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -607,7 +607,6 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { BOOST_LOG_TRIVIAL(debug) << "Beginning sorting process."; list messages; - list plugins; boost::thread_group group; unsigned int lang; @@ -633,38 +632,9 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { messages.push_back(loot::Message(loot::Message::error, (format(loc::translate("Masterlist parsing failed. Details: %1%")) % e.what()).str())); } }); - - //First calculate the mean plugin size. Store it temporarily in a map to reduce filesystem lookups and file size recalculation. - size_t meanFileSize = 0; - boost::unordered_map tempMap; - for (fs::directory_iterator it(_game->DataPath()); it != fs::directory_iterator(); ++it) { - if (fs::is_regular_file(it->status()) && IsPlugin(it->path().string())) { - - size_t fileSize = fs::file_size(it->path()); - meanFileSize += fileSize; - - tempMap.emplace(it->path().filename().string(), fileSize); - } - } - meanFileSize /= tempMap.size(); - - //Now load plugins. - PluginsLoader pll(plugins, *_game); - for (const auto &pluginPair: tempMap) { - - BOOST_LOG_TRIVIAL(info) << "Found plugin: " << pluginPair.first; - - plugins.push_back(loot::Plugin(pluginPair.first)); - - if (pluginPair.second > meanFileSize) { - pll.skipPlugins.insert(pluginPair.first); - PluginLoader pl(plugins.back(), *_game); - group.create_thread(pl); - } - - progDia->Pulse(); - } - group.create_thread(pll); + group.create_thread([this]() { + this->_game->LoadPlugins(false); + }); group.join_all(); //Now load userlist. @@ -685,48 +655,28 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { // Merge & Check Metadata /////////////////////////////////////////////////////// - if (fs::exists(_game->MasterlistPath()) || fs::exists(_game->UserlistPath())) { + //Merge all global message lists. + BOOST_LOG_TRIVIAL(debug) << "Merging all global message lists."; + if (!_game->masterlist.messages.empty()) + messages.insert(messages.end(), _game->masterlist.messages.begin(), _game->masterlist.messages.end()); + if (!_game->userlist.messages.empty()) + messages.insert(messages.end(), _game->userlist.messages.begin(), _game->userlist.messages.end()); - - //Merge all global message lists. - BOOST_LOG_TRIVIAL(debug) << "Merging all global message lists."; - if (!_game->masterlist.messages.empty()) - messages.insert(messages.end(), _game->masterlist.messages.begin(), _game->masterlist.messages.end()); - if (!_game->userlist.messages.empty()) - messages.insert(messages.end(), _game->userlist.messages.begin(), _game->userlist.messages.end()); - - //Evaluate any conditions in the global messages. - BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; - try { - list::iterator it=messages.begin(); - while (it != messages.end()) { - if (!it->EvalCondition(*_game, lang)) - it = messages.erase(it); - else - ++it; - } - } - catch (std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what(); - messages.push_back(loot::Message(loot::Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str())); - } - - //Merge plugin list and masterlist. - BOOST_LOG_TRIVIAL(debug) << "Merging plugin list and masterlist data."; - for (auto &plugin : plugins) { - BOOST_LOG_TRIVIAL(trace) << "Merging for plugin \"" << plugin.Name() << "\""; - - //Check if there is a plugin entry in the masterlist. This will also find matching regex entries. - list::iterator pos = std::find(_game->masterlist.plugins.begin(), _game->masterlist.plugins.end(), plugin); - - if (pos != _game->masterlist.plugins.end()) { - BOOST_LOG_TRIVIAL(trace) << "Merging masterlist data down to plugin list data."; - plugin.MergeMetadata(*pos); - } - - progDia->Pulse(); + //Evaluate any conditions in the global messages. + BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; + try { + list::iterator it=messages.begin(); + while (it != messages.end()) { + if (!it->EvalCondition(*_game, lang)) + it = messages.erase(it); + else + ++it; } } + catch (std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what(); + messages.push_back(loot::Message(loot::Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str())); + } progDia->Update(800, translate("Building plugin graph...")); @@ -745,6 +695,10 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { */ //Check for back-edges, then perform a topological sort. + list plugins; + for (auto &plugin : _game->plugins) { + plugins.push_back(plugin.second); + } try { bool applyLoadOrder = false; @@ -760,8 +714,16 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { for (boost::tie(vit, vitend) = boost::vertices(graph); vit != vitend; ++vit) { BOOST_LOG_TRIVIAL(trace) << "Merging for plugin \"" << graph[*vit].Name() << "\""; + //Check if there is a plugin entry in the masterlist. This will also find matching regex entries. + list::iterator pos = std::find(_game->masterlist.plugins.begin(), _game->masterlist.plugins.end(), graph[*vit]); + + if (pos != _game->masterlist.plugins.end()) { + BOOST_LOG_TRIVIAL(trace) << "Merging masterlist data down to plugin list data."; + graph[*vit].MergeMetadata(*pos); + } + //Check if there is a plugin entry in the userlist. This will also find matching regex entries. - list::iterator pos = std::find(_game->userlist.plugins.begin(), _game->userlist.plugins.end(), graph[*vit]); + pos = std::find(_game->userlist.plugins.begin(), _game->userlist.plugins.end(), graph[*vit]); if (pos != _game->userlist.plugins.end() && pos->Enabled()) { BOOST_LOG_TRIVIAL(trace) << "Merging userlist data down to plugin list data.";