diff --git a/src/api/api.cpp b/src/api/api.cpp index ca979866..b08f282b 100644 --- a/src/api/api.cpp +++ b/src/api/api.cpp @@ -363,9 +363,9 @@ LOOT_API unsigned int loot_load_lists(loot_db db, const char * const masterlistP db->extTagMap = nullptr; db->extMessageArray = nullptr; - db->masterlist = temp; + db->GetMasterlist() = temp; db->rawMetadata = temp; - db->userlist = userTemp; + db->GetUserlist() = userTemp; db->rawUserMetadata = userTemp; return loot_ok; @@ -406,8 +406,8 @@ LOOT_API unsigned int loot_eval_lists(loot_db db, const unsigned int language) { catch (loot::error& e) { return c_error(e); } - db->masterlist = temp; - db->userlist = userTemp; + db->GetMasterlist() = temp; + db->GetUserlist() = userTemp; return loot_ok; } @@ -575,12 +575,12 @@ LOOT_API unsigned int loot_get_tag_map(loot_db db, char *** const tagMap, size_t std::set allTags; - for (const auto &plugin : db->masterlist.Plugins()) { + for (const auto &plugin : db->GetMasterlist().Plugins()) { for (const auto &tag : plugin.Tags()) { allTags.insert(tag.Name()); } } - for (const auto &plugin : db->userlist.Plugins()) { + for (const auto &plugin : db->GetUserlist().Plugins()) { for (const auto &tag : plugin.Tags()) { allTags.insert(tag.Name()); } @@ -649,7 +649,7 @@ LOOT_API unsigned int loot_get_plugin_tags(loot_db db, const char * const plugin *numTags_removed = 0; std::set tagsAdded, tagsRemoved; - loot::PluginMetadata p = db->masterlist.FindPlugin(loot::PluginMetadata(plugin)); + loot::PluginMetadata p = db->GetMasterlist().FindPlugin(loot::PluginMetadata(plugin)); for (const auto &tag : p.Tags()) { if (tag.IsAddition()) tagsAdded.insert(tag.Name()); @@ -657,7 +657,7 @@ LOOT_API unsigned int loot_get_plugin_tags(loot_db db, const char * const plugin tagsRemoved.insert(tag.Name()); } - p = db->userlist.FindPlugin(loot::PluginMetadata(plugin)); + p = db->GetUserlist().FindPlugin(loot::PluginMetadata(plugin)); *userlistModified = !p.Tags().empty(); for (const auto &tag : p.Tags()) { *userlistModified = true; @@ -730,10 +730,10 @@ LOOT_API unsigned int loot_get_plugin_messages(loot_db db, const char * const pl *messages = nullptr; *numMessages = 0; - loot::PluginMetadata p = db->masterlist.FindPlugin(loot::PluginMetadata(plugin)); + loot::PluginMetadata p = db->GetMasterlist().FindPlugin(loot::PluginMetadata(plugin)); std::list pluginMessages(p.Messages()); - p = db->userlist.FindPlugin(loot::PluginMetadata(plugin)); + p = db->GetUserlist().FindPlugin(loot::PluginMetadata(plugin)); std::list temp(p.Messages()); pluginMessages.insert(pluginMessages.end(), temp.begin(), temp.end()); @@ -766,8 +766,8 @@ LOOT_API unsigned int loot_get_dirty_info(loot_db db, const char * const plugin, *needsCleaning = loot_needs_cleaning_unknown; // Is there any dirty info? Testing for applicability happens in loot_eval_lists(). - if (!db->masterlist.FindPlugin(loot::PluginMetadata(plugin)).DirtyInfo().empty() - || !db->userlist.FindPlugin(loot::PluginMetadata(plugin)).DirtyInfo().empty()) { + if (!db->GetMasterlist().FindPlugin(loot::PluginMetadata(plugin)).DirtyInfo().empty() + || !db->GetUserlist().FindPlugin(loot::PluginMetadata(plugin)).DirtyInfo().empty()) { *needsCleaning = loot_needs_cleaning_yes; } @@ -775,9 +775,9 @@ LOOT_API unsigned int loot_get_dirty_info(loot_db db, const char * const plugin, // This isn't a very reliable system, because if the lists have been evaluated in some language // other than English, the strings will be in different languages (and the API can't tell what they'd be) // and the strings may be non-standard and begin with something other than "Do not clean." anyway. - std::list messages(db->masterlist.FindPlugin(loot::PluginMetadata(plugin)).Messages()); + std::list messages(db->GetMasterlist().FindPlugin(loot::PluginMetadata(plugin)).Messages()); - std::list temp(db->userlist.FindPlugin(loot::PluginMetadata(plugin)).Messages()); + std::list temp(db->GetUserlist().FindPlugin(loot::PluginMetadata(plugin)).Messages()); messages.insert(messages.end(), temp.begin(), temp.end()); for (const auto& message : messages) { @@ -804,7 +804,7 @@ LOOT_API unsigned int loot_write_minimal_list(loot_db db, const char * const out if (boost::filesystem::exists(outputFile) && !overwrite) return c_error(loot_error_file_write_fail, "Output file exists but overwrite is not set to true."); - loot::Masterlist temp = db->masterlist; + loot::Masterlist temp = db->GetMasterlist(); std::unordered_set minimalPlugins; for (const auto &plugin : temp.Plugins()) { loot::PluginMetadata p(plugin.Name()); diff --git a/src/backend/game/game.cpp b/src/backend/game/game.cpp index 930ae034..d7ae7071 100644 --- a/src/backend/game/game.cpp +++ b/src/backend/game/game.cpp @@ -50,31 +50,8 @@ namespace loot { .SetRegistryKey(gameSettings.RegistryKey()); } - Game::Game(const Game& game) : - GameSettings(game), - LoadOrderHandler(game), - GameCache(game), - masterlist(game.masterlist), - userlist(game.userlist), - plugins(game.plugins), - _pluginsFullyLoaded(game.ArePluginsFullyLoaded()) {} - Game::Game(const unsigned int gameCode, const std::string& folder) : GameSettings(gameCode, folder), _pluginsFullyLoaded(false) {} - Game& Game::operator= (const Game& game) { - if (&game != this) { - GameSettings::operator=(game); - LoadOrderHandler::operator=(game); - GameCache::operator=(game); - - masterlist = game.masterlist; - userlist = game.userlist; - plugins = game.plugins; - _pluginsFullyLoaded = game.ArePluginsFullyLoaded(); - } - return *this; - } - void Game::Init(bool createFolder, const boost::filesystem::path& gameLocalAppData) { if (Id() != Game::tes4 && Id() != Game::tes5 && Id() != Game::fo3 && Id() != Game::fonv && Id() != Game::fo4) { throw error(error::invalid_args, lc::translate("Invalid game ID supplied.").str()); @@ -156,11 +133,6 @@ namespace loot { } meanFileSize /= sizeMap.size(); //Rounding error, but not important. - // Reserve space in the plugins unordered_map to speed up inserting - // later and more importantly avoid any inserts invalidating - // iterators. - plugins.reserve(sizeMap.size()); - // Get the number of threads to use. // hardware_concurrency() may be zero, if so then use only one thread. size_t threadsToUse = std::min((size_t)thread::hardware_concurrency(), sizeMap.size()); @@ -190,7 +162,7 @@ namespace loot { threads.push_back(thread([&]() { for (auto pluginName : pluginGroup) { BOOST_LOG_TRIVIAL(trace) << "Loading " << pluginName; - addPlugin(Plugin(*this, pluginName, headersOnly)); + AddPlugin(Plugin(*this, pluginName, headersOnly)); } })); } @@ -209,16 +181,12 @@ namespace loot { } bool Game::IsPluginActive(const std::string& pluginName) const { - auto it = plugins.find(boost::locale::to_lower(pluginName)); - if (it != end(plugins)) - return it->second.IsActive(); - else + try { + return GetPlugin(pluginName).IsActive(); + } + catch (...) { return LoadOrderHandler::IsPluginActive(pluginName); - } - - void Game::addPlugin(const Plugin&& plugin) { - std::lock_guard lock(mutex); - plugins.emplace(boost::locale::to_lower(plugin.Name()), plugin); + } } std::list ToGames(const std::list& settings) { diff --git a/src/backend/game/game.h b/src/backend/game/game.h index 4b3afd07..43f7cb3a 100644 --- a/src/backend/game/game.h +++ b/src/backend/game/game.h @@ -28,12 +28,8 @@ #include "game_cache.h" #include "game_settings.h" #include "load_order_handler.h" -#include "../plugin/plugin.h" -#include "../metadata_list.h" -#include "../masterlist.h" #include -#include #include @@ -43,11 +39,8 @@ namespace loot { //Game functions. Game(); //Sets game to LOOT_Game::autodetect, with all other vars being empty. Game(const GameSettings& gameSettings); - Game(const Game& game); Game(const unsigned int baseGameCode, const std::string& lootFolder = ""); - Game& operator= (const Game& game); - void Init(bool createFolder, const boost::filesystem::path& gameLocalAppData = ""); void RedatePlugins(); //Change timestamps to match load order (Skyrim only). @@ -58,16 +51,8 @@ namespace loot { // Check if the plugin is active by using the cached value if // available, and otherwise asking the load order handler. bool IsPluginActive(const std::string& pluginName) const; - - //Plugin data and metadata lists. - Masterlist masterlist; - MetadataList userlist; - std::unordered_map plugins; //Map so that plugin data can be edited. private: bool _pluginsFullyLoaded; - std::mutex mutex; - - void addPlugin(const Plugin&& plugin); }; std::list ToGames(const std::list& settings); diff --git a/src/backend/game/game_cache.cpp b/src/backend/game/game_cache.cpp index 25f546d5..e818a840 100644 --- a/src/backend/game/game_cache.cpp +++ b/src/backend/game/game_cache.cpp @@ -40,15 +40,31 @@ namespace lc = boost::locale; namespace loot { GameCache::GameCache() {} - GameCache::GameCache(const GameCache& cache) - : conditionCache(cache.conditionCache) {} + GameCache::GameCache(const GameCache& cache) : + masterlist(cache.masterlist), + userlist(cache.userlist), + conditionCache(cache.conditionCache), + plugins(cache.plugins) {} GameCache& GameCache::operator=(const GameCache& cache) { - conditionCache = cache.conditionCache; + if (&cache != this) { + masterlist = cache.masterlist; + userlist = cache.userlist; + conditionCache = cache.conditionCache; + plugins = cache.plugins; + } return *this; } + Masterlist & GameCache::GetMasterlist() { + return masterlist; + } + + MetadataList & GameCache::GetUserlist() { + return userlist; + } + void GameCache::CacheCondition(const std::string& condition, bool result) { std::lock_guard guard(mutex); conditionCache.insert(pair(boost::locale::to_lower(condition), result)); @@ -65,6 +81,30 @@ namespace loot { return std::pair(false, false); } + std::set GameCache::GetPlugins() const { + std::set output; + std::transform(begin(plugins), + end(plugins), + inserter>(output, begin(output)), + [](const pair& pluginPair) { + return pluginPair.second; + }); + return output; + } + + const Plugin& GameCache::GetPlugin(const std::string & pluginName) const { + auto it = plugins.find(boost::locale::to_lower(pluginName)); + if (it != end(plugins)) + return it->second; + + throw error(error::invalid_args, "No plugin \"" + pluginName + "\" exists."); + } + + void GameCache::AddPlugin(const Plugin&& plugin) { + std::lock_guard lock(mutex); + plugins.emplace(boost::locale::to_lower(plugin.Name()), plugin); + } + void GameCache::ClearCache() { std::lock_guard guard(mutex); diff --git a/src/backend/game/game_cache.h b/src/backend/game/game_cache.h index bccba2cf..b8d88fbf 100644 --- a/src/backend/game/game_cache.h +++ b/src/backend/game/game_cache.h @@ -25,11 +25,14 @@ #ifndef __LOOT_GAME_CRC_CACHE__ #define __LOOT_GAME_CRC_CACHE__ -#include +#include "../metadata_list.h" +#include "../masterlist.h" +#include "../plugin/plugin.h" + #include +#include #include #include -#include namespace loot { class GameCache { @@ -39,15 +42,23 @@ namespace loot { GameCache& operator=(const GameCache& cache); - void CacheCondition(const std::string& condition, bool result); + Masterlist& GetMasterlist(); + MetadataList& GetUserlist(); // Returns false for second bool if no cached condition. std::pair GetCachedCondition(const std::string& condition) const; + void CacheCondition(const std::string& condition, bool result); + + std::set GetPlugins() const; + const Plugin& GetPlugin(const std::string & pluginName) const; + void AddPlugin(const Plugin&& plugin); void ClearCache(); private: - //Caches for condition results, CRCs and active plugins. + Masterlist masterlist; + MetadataList userlist; std::unordered_map conditionCache; + std::unordered_map plugins; mutable std::mutex mutex; }; diff --git a/src/backend/metadata/condition_grammar.h b/src/backend/metadata/condition_grammar.h index 3f29628a..f4532840 100644 --- a/src/backend/metadata/condition_grammar.h +++ b/src/backend/metadata/condition_grammar.h @@ -293,9 +293,10 @@ namespace loot { else { // CRC could be for a plugin or a file. // Get the CRC from the game plugin cache if possible. - auto pluginPairIt = _game->plugins.find(boost::locale::to_lower(file)); - if (pluginPairIt != _game->plugins.end()) - crc = pluginPairIt->second.Crc(); + try { + crc = _game->GetPlugin(file).Crc(); + } + catch (...) {} if (crc == 0) { if (boost::filesystem::exists(_game->DataPath() / file)) diff --git a/src/backend/metadata/plugin_dirty_info.cpp b/src/backend/metadata/plugin_dirty_info.cpp index 03f68346..0a847d4f 100644 --- a/src/backend/metadata/plugin_dirty_info.cpp +++ b/src/backend/metadata/plugin_dirty_info.cpp @@ -98,9 +98,10 @@ namespace loot { uint32_t crc = 0; // Get the CRC from the game plugin cache if possible. - auto pluginPairIt = game.plugins.find(boost::locale::to_lower(pluginName)); - if (pluginPairIt != game.plugins.end()) - crc = pluginPairIt->second.Crc(); + try { + crc = game.GetPlugin(pluginName).Crc(); + } + catch (...) {} // Otherwise calculate it from the file. if (crc == 0) { diff --git a/src/backend/plugin/plugin.cpp b/src/backend/plugin/plugin.cpp index c94a1318..aad6cee4 100644 --- a/src/backend/plugin/plugin.cpp +++ b/src/backend/plugin/plugin.cpp @@ -184,6 +184,10 @@ namespace loot { return false; } + bool Plugin::operator < (const Plugin & rhs) const { + return boost::ilexicographical_compare(Name(), rhs.Name());; + } + bool Plugin::IsActive() const { return _isActive; } diff --git a/src/backend/plugin/plugin.h b/src/backend/plugin/plugin.h index 36a0ffe0..7de75fd3 100644 --- a/src/backend/plugin/plugin.h +++ b/src/backend/plugin/plugin.h @@ -62,6 +62,8 @@ namespace loot { //Validity checks. bool CheckInstallValidity(const Game& game); //Checks that reqs and masters are all present, and that no incs are present. Returns true if the plugin is dirty. static bool IsValid(const std::string& filename, const Game& game); + + bool operator < (const Plugin& rhs) const; private: bool _isEmpty; // Does the plugin contain any records other than the TES4 header? bool _isActive; diff --git a/src/backend/plugin_sorter.cpp b/src/backend/plugin_sorter.cpp index 71dd420c..8564e551 100644 --- a/src/backend/plugin_sorter.cpp +++ b/src/backend/plugin_sorter.cpp @@ -177,21 +177,16 @@ namespace loot { // Using a set of plugin names followed by finding the matching key // in the unordered map, as it's probably faster than copying the // full plugin objects then sorting them. - set pluginNames; - for (const auto &plugin : game.plugins) { - pluginNames.insert(plugin.first); - } - - for (const auto &plugin : pluginNames) { - vertex_t v = boost::add_vertex(game.plugins.find(plugin)->second, graph); + for (const auto &plugin : game.GetPlugins()) { + vertex_t v = boost::add_vertex(plugin, graph); BOOST_LOG_TRIVIAL(trace) << "Merging for plugin \"" << graph[v].Name() << "\""; //Check if there is a plugin entry in the masterlist. This will also find matching regex entries. BOOST_LOG_TRIVIAL(trace) << "Merging masterlist data down to plugin list data."; - graph[v].MergeMetadata(game.masterlist.FindPlugin(graph[v])); + graph[v].MergeMetadata(game.GetMasterlist().FindPlugin(graph[v])); //Check if there is a plugin entry in the userlist. This will also find matching regex entries. - PluginMetadata ulistPlugin = game.userlist.FindPlugin(graph[v]); + PluginMetadata ulistPlugin = game.GetUserlist().FindPlugin(graph[v]); if (!ulistPlugin.HasNameOnly() && ulistPlugin.Enabled()) { BOOST_LOG_TRIVIAL(trace) << "Merging userlist data down to plugin list data."; diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 9269d72e..5213ad26 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -400,7 +400,7 @@ namespace loot { void Handler::GetConflictingPlugins(const std::string& pluginName, CefRefPtr frame, CefRefPtr callback) { BOOST_LOG_TRIVIAL(debug) << "Searching for plugins that conflict with " << pluginName; - auto pluginIt = _lootState.CurrentGame().plugins.find(boost::locale::to_lower(pluginName)); + auto plugin = _lootState.CurrentGame().GetPlugin(pluginName); // Checking for FormID overlap will only work if the plugins have been loaded, so check if // the plugins have been fully loaded, and if not load all plugins. @@ -411,13 +411,13 @@ namespace loot { SendProgressUpdate(frame, loc::translate("Checking for conflicting plugins...")); YAML::Node node; - for (const auto& pluginPair : _lootState.CurrentGame().plugins) { + for (const auto& otherPlugin : _lootState.CurrentGame().GetPlugins()) { YAML::Node pluginNode; - pluginNode["crc"] = pluginPair.second.Crc(); - pluginNode["isEmpty"] = pluginPair.second.IsEmpty(); - if (pluginIt != _lootState.CurrentGame().plugins.end() && pluginIt->second.DoFormIDsOverlap(pluginPair.second)) { - BOOST_LOG_TRIVIAL(debug) << "Found conflicting plugin: " << pluginPair.second.Name(); + pluginNode["crc"] = otherPlugin.Crc(); + pluginNode["isEmpty"] = otherPlugin.IsEmpty(); + if (plugin.DoFormIDsOverlap(otherPlugin)) { + BOOST_LOG_TRIVIAL(debug) << "Found conflicting plugin: " << otherPlugin.Name(); pluginNode["conflicts"] = true; } else { @@ -425,13 +425,13 @@ namespace loot { } // Plugin loading may have produced an error message, so rederive displayed data. - YAML::Node derivedNode = GenerateDerivedMetadata(pluginPair.second.Name()); + YAML::Node derivedNode = GenerateDerivedMetadata(otherPlugin.Name()); for (const auto &pair : derivedNode) { const string key = pair.first.as(); pluginNode[key] = pair.second; } - node[pluginPair.second.Name()] = pluginNode; + node[otherPlugin.Name()] = pluginNode; } if (node.size() > 0) @@ -444,8 +444,8 @@ namespace loot { BOOST_LOG_TRIVIAL(debug) << "Copying metadata for plugin " << pluginName; // Get metadata from masterlist and userlist. - PluginMetadata plugin = _lootState.CurrentGame().masterlist.FindPlugin(pluginName); - plugin.MergeMetadata(_lootState.CurrentGame().userlist.FindPlugin(pluginName)); + PluginMetadata plugin = _lootState.CurrentGame().GetMasterlist().FindPlugin(pluginName); + plugin.MergeMetadata(_lootState.CurrentGame().GetUserlist().FindPlugin(pluginName)); // Generate text representation. string text; @@ -465,10 +465,10 @@ namespace loot { std::string Handler::ClearPluginMetadata(const std::string& pluginName) { BOOST_LOG_TRIVIAL(debug) << "Clearing user metadata for plugin " << pluginName; - _lootState.CurrentGame().userlist.ErasePlugin(PluginMetadata(pluginName)); + _lootState.CurrentGame().GetUserlist().ErasePlugin(PluginMetadata(pluginName)); // Save userlist edits. - _lootState.CurrentGame().userlist.Save(_lootState.CurrentGame().UserlistPath()); + _lootState.CurrentGame().GetUserlist().Save(_lootState.CurrentGame().UserlistPath()); // Now rederive the displayed metadata from the masterlist. YAML::Node derivedMetadata = GenerateDerivedMetadata(pluginName); @@ -484,7 +484,7 @@ namespace loot { PluginMetadata newUserlistEntry(pluginMetadata["name"].as()); // Find existing userlist entry. - PluginMetadata ulistPlugin = _lootState.CurrentGame().userlist.FindPlugin(newUserlistEntry); + PluginMetadata ulistPlugin = _lootState.CurrentGame().GetUserlist().FindPlugin(newUserlistEntry); // First sort out the priority value. This is only given if it was changed. BOOST_LOG_TRIVIAL(trace) << "Calculating userlist metadata priority value from Javascript variables."; @@ -537,28 +537,28 @@ namespace loot { // For cleanliness, only data that does not duplicate masterlist and plugin data should be retained, so diff that. BOOST_LOG_TRIVIAL(trace) << "Removing any user metadata that duplicates masterlist metadata."; - auto pluginIt = _lootState.CurrentGame().plugins.find(boost::locale::to_lower(newUserlistEntry.Name())); - if (pluginIt != _lootState.CurrentGame().plugins.end()) { - Plugin tempPlugin(pluginIt->second); - tempPlugin.MergeMetadata(_lootState.CurrentGame().masterlist.FindPlugin(newUserlistEntry)); + try { + Plugin tempPlugin(_lootState.CurrentGame().GetPlugin(newUserlistEntry.Name())); + tempPlugin.MergeMetadata(_lootState.CurrentGame().GetMasterlist().FindPlugin(newUserlistEntry)); newUserlistEntry = newUserlistEntry.NewMetadata(tempPlugin); } - else - newUserlistEntry = newUserlistEntry.NewMetadata(_lootState.CurrentGame().masterlist.FindPlugin(newUserlistEntry)); + catch (...) { + newUserlistEntry = newUserlistEntry.NewMetadata(_lootState.CurrentGame().GetMasterlist().FindPlugin(newUserlistEntry)); + } // Now erase any existing userlist entry. if (!ulistPlugin.HasNameOnly()) { BOOST_LOG_TRIVIAL(trace) << "Erasing the existing userlist entry."; - _lootState.CurrentGame().userlist.ErasePlugin(ulistPlugin); + _lootState.CurrentGame().GetUserlist().ErasePlugin(ulistPlugin); } // Add a new userlist entry if necessary. if (!newUserlistEntry.HasNameOnly()) { BOOST_LOG_TRIVIAL(trace) << "Adding new metadata to new userlist entry."; - _lootState.CurrentGame().userlist.AddPlugin(newUserlistEntry); + _lootState.CurrentGame().GetUserlist().AddPlugin(newUserlistEntry); } // Save edited userlist. - _lootState.CurrentGame().userlist.Save(_lootState.CurrentGame().UserlistPath()); + _lootState.CurrentGame().GetUserlist().Save(_lootState.CurrentGame().UserlistPath()); // Now rederive the derived metadata. BOOST_LOG_TRIVIAL(trace) << "Returning newly derived display metadata."; @@ -642,17 +642,18 @@ namespace loot { // First clear CRC and condition caches, otherwise they could lead to incorrect evaluations. _lootState.CurrentGame().ClearCache(); - bool isFirstLoad = _lootState.CurrentGame().plugins.empty(); + bool isFirstLoad = _lootState.CurrentGame().GetPlugins().empty(); _lootState.CurrentGame().LoadPlugins(true); //Sort plugins into their load order. list installed; list loadOrder = _lootState.CurrentGame().GetLoadOrder(); for (const auto &pluginName : loadOrder) { - const auto pos = _lootState.CurrentGame().plugins.find(boost::locale::to_lower(pluginName)); - - if (pos != _lootState.CurrentGame().plugins.end()) - installed.push_back(pos->second); + try { + const auto plugin = _lootState.CurrentGame().GetPlugin(pluginName); + installed.push_back(plugin); + } + catch (...) {} } list parsingErrors; @@ -662,7 +663,7 @@ namespace loot { SendProgressUpdate(frame, loc::translate("Parsing masterlist...")); BOOST_LOG_TRIVIAL(debug) << "Parsing masterlist."; try { - _lootState.CurrentGame().masterlist.Load(_lootState.CurrentGame().MasterlistPath()); + _lootState.CurrentGame().GetMasterlist().Load(_lootState.CurrentGame().MasterlistPath()); } catch (exception &e) { parsingErrors.push_back(Message(Message::error, (boost::format(loc::translate( @@ -679,7 +680,7 @@ namespace loot { SendProgressUpdate(frame, loc::translate("Parsing userlist...")); BOOST_LOG_TRIVIAL(debug) << "Parsing userlist."; try { - _lootState.CurrentGame().userlist.Load(_lootState.CurrentGame().UserlistPath()); + _lootState.CurrentGame().GetUserlist().Load(_lootState.CurrentGame().UserlistPath()); } catch (exception &e) { parsingErrors.push_back(Message(Message::error, (boost::format(loc::translate( @@ -710,7 +711,7 @@ namespace loot { // Store the masterlist revision and date. try { - Masterlist::Info info = _lootState.CurrentGame().masterlist.GetInfo(_lootState.CurrentGame().MasterlistPath(), true); + Masterlist::Info info = _lootState.CurrentGame().GetMasterlist().GetInfo(_lootState.CurrentGame().MasterlistPath(), true); gameNode["masterlist"]["revision"] = info.revision; gameNode["masterlist"]["date"] = info.date; } @@ -730,11 +731,11 @@ namespace loot { // description as part of it. BOOST_LOG_TRIVIAL(trace) << "Getting masterlist metadata for: " << plugin.Name(); Plugin mlistPlugin(plugin); - mlistPlugin.MergeMetadata(_lootState.CurrentGame().masterlist.FindPlugin(plugin)); + mlistPlugin.MergeMetadata(_lootState.CurrentGame().GetMasterlist().FindPlugin(plugin)); // Now do the same again for any userlist data. BOOST_LOG_TRIVIAL(trace) << "Getting userlist metadata for: " << plugin.Name(); - PluginMetadata ulistPlugin(_lootState.CurrentGame().userlist.FindPlugin(plugin)); + PluginMetadata ulistPlugin(_lootState.CurrentGame().GetUserlist().FindPlugin(plugin)); pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object. pluginNode["name"] = plugin.Name(); @@ -797,11 +798,11 @@ namespace loot { //Evaluate any conditions in the global messages. BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; list messages = parsingErrors; - auto metadataListMessages = _lootState.CurrentGame().masterlist.Messages(); + auto metadataListMessages = _lootState.CurrentGame().GetMasterlist().Messages(); messages.insert(end(messages), begin(metadataListMessages), end(metadataListMessages)); - metadataListMessages = _lootState.CurrentGame().userlist.Messages(); + metadataListMessages = _lootState.CurrentGame().GetUserlist().Messages(); messages.insert(messages.end(), begin(metadataListMessages), end(metadataListMessages)); @@ -850,20 +851,20 @@ namespace loot { bool wasChanged = true; try { SendProgressUpdate(frame, loc::translate("Updating and parsing masterlist...")); - wasChanged = _lootState.CurrentGame().masterlist.Update(_lootState.CurrentGame()); + wasChanged = _lootState.CurrentGame().GetMasterlist().Update(_lootState.CurrentGame()); } catch (loot::error &e) { if (e.code() == loot::error::ok) { // There was a parsing error, but roll-back was successful, so the process // should still complete. - _lootState.CurrentGame().masterlist.AppendMessage(Message(Message::error, e.what())); + _lootState.CurrentGame().GetMasterlist().AppendMessage(Message(Message::error, e.what())); wasChanged = true; } else { // Error wasn't a parsing error. Need to try parsing masterlist if it exists. try { - _lootState.CurrentGame().masterlist.Load(_lootState.CurrentGame().MasterlistPath()); + _lootState.CurrentGame().GetMasterlist().Load(_lootState.CurrentGame().MasterlistPath()); } catch (...) {} } @@ -878,7 +879,7 @@ namespace loot { // Store the masterlist revision and date. try { - Masterlist::Info info = _lootState.CurrentGame().masterlist.GetInfo(_lootState.CurrentGame().MasterlistPath(), true); + Masterlist::Info info = _lootState.CurrentGame().GetMasterlist().GetInfo(_lootState.CurrentGame().MasterlistPath(), true); gameNode["masterlist"]["revision"] = info.revision; gameNode["masterlist"]["date"] = info.date; } @@ -887,9 +888,9 @@ namespace loot { gameNode["masterlist"]["date"] = e.what(); } - for (const auto& pluginPair : _lootState.CurrentGame().plugins) { - Plugin mlistPlugin(pluginPair.second); - mlistPlugin.MergeMetadata(_lootState.CurrentGame().masterlist.FindPlugin(pluginPair.second)); + for (const auto& plugin : _lootState.CurrentGame().GetPlugins()) { + Plugin mlistPlugin(plugin); + mlistPlugin.MergeMetadata(_lootState.CurrentGame().GetMasterlist().FindPlugin(plugin)); YAML::Node pluginNode; if (!mlistPlugin.HasNameOnly()) { @@ -905,7 +906,7 @@ namespace loot { // Now merge masterlist and userlist metadata and evaluate, // putting any resulting metadata into the base of the pluginNode. - YAML::Node derivedNode = GenerateDerivedMetadata(pluginPair.second.Name()); + YAML::Node derivedNode = GenerateDerivedMetadata(plugin.Name()); for (const auto &pair : derivedNode) { const string key = pair.first.as(); @@ -917,7 +918,7 @@ namespace loot { //Evaluate any conditions in the global messages. BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; - list messages = _lootState.CurrentGame().masterlist.Messages(); + list messages = _lootState.CurrentGame().GetMasterlist().Messages(); try { list::iterator it = messages.begin(); while (it != messages.end()) { @@ -954,16 +955,16 @@ namespace loot { BOOST_LOG_TRIVIAL(debug) << "Clearing all user metadata."; // Record which plugins have userlist entries. vector userlistPlugins; - for (const auto &plugin : _lootState.CurrentGame().userlist.Plugins()) { + for (const auto &plugin : _lootState.CurrentGame().GetUserlist().Plugins()) { userlistPlugins.push_back(plugin.Name()); } BOOST_LOG_TRIVIAL(trace) << "User metadata exists for " << userlistPlugins.size() << " plugins."; // Clear the user metadata. - _lootState.CurrentGame().userlist.clear(); + _lootState.CurrentGame().GetUserlist().clear(); // Save userlist edits. - _lootState.CurrentGame().userlist.Save(_lootState.CurrentGame().UserlistPath()); + _lootState.CurrentGame().GetUserlist().Save(_lootState.CurrentGame().UserlistPath()); // Regenerate the derived metadata (priority, messages, tags and dirty state) // for any plugins with userlist entries. @@ -1074,15 +1075,16 @@ namespace loot { YAML::Node Handler::GenerateDerivedMetadata(const std::string& pluginName) { // Now rederive the displayed metadata from the masterlist and userlist. - auto pluginIt = _lootState.CurrentGame().plugins.find(boost::locale::to_lower(pluginName)); - if (pluginIt != _lootState.CurrentGame().plugins.end()) { - PluginMetadata master(_lootState.CurrentGame().masterlist.FindPlugin(pluginIt->second)); - PluginMetadata user(_lootState.CurrentGame().userlist.FindPlugin(pluginIt->second)); + try { + auto plugin = _lootState.CurrentGame().GetPlugin(pluginName); + PluginMetadata master(_lootState.CurrentGame().GetMasterlist().FindPlugin(plugin)); + PluginMetadata user(_lootState.CurrentGame().GetUserlist().FindPlugin(plugin)); - return this->GenerateDerivedMetadata(pluginIt->second, master, user); + return this->GenerateDerivedMetadata(plugin, master, user); + } + catch (...) { + return YAML::Node(); } - - return YAML::Node(); } void Handler::CopyToClipboard(const std::string& text) { diff --git a/src/tests/backend/game/test_game.h b/src/tests/backend/game/test_game.h index 3a1157d7..cb4cf5b4 100644 --- a/src/tests/backend/game/test_game.h +++ b/src/tests/backend/game/test_game.h @@ -216,11 +216,11 @@ TEST_F(Game, LoadPlugins) { game.SetGamePath(dataPath.parent_path()); EXPECT_NO_THROW(game.LoadPlugins(false)); - EXPECT_EQ(11, game.plugins.size()); + EXPECT_EQ(11, game.GetPlugins().size()); // Check that all the plugins' data have loaded correctly. - ASSERT_NE(game.plugins.end(), game.plugins.find("skyrim.esm")); - loot::Plugin plugin = game.plugins.find("skyrim.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("Skyrim.esm")); + loot::Plugin plugin = game.GetPlugin("Skyrim.esm"); EXPECT_EQ("Skyrim.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -241,8 +241,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0x187BE342, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank.esm")); - plugin = game.plugins.find("blank.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("blank.esm")); + plugin = game.GetPlugin("blank.esm"); EXPECT_EQ("Blank.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -263,8 +263,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0x187BE342, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different.esm")); - plugin = game.plugins.find("blank - different.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("Blank - Different.esm")); + plugin = game.GetPlugin("Blank - Different.esm"); EXPECT_EQ("Blank - Different.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -284,8 +284,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0x64B9F757, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - master dependent.esm")); - plugin = game.plugins.find("blank - master dependent.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esm")); + plugin = game.GetPlugin("blank - master dependent.esm"); EXPECT_EQ("Blank - Master Dependent.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -306,8 +306,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0xB2D4119E, plugin.Crc()); EXPECT_EQ(4, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different master dependent.esm")); - plugin = game.plugins.find("blank - different master dependent.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esm")); + plugin = game.GetPlugin("blank - different master dependent.esm"); EXPECT_EQ("Blank - Different Master Dependent.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -327,8 +327,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0xAADF6710, plugin.Crc()); EXPECT_EQ(4, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank.esp")); - plugin = game.plugins.find("blank.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank.esp")); + plugin = game.GetPlugin("blank.esp"); EXPECT_EQ("Blank.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -345,8 +345,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0x24F0E2A1, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different.esp")); - plugin = game.plugins.find("blank - different.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - different.esp")); + plugin = game.GetPlugin("blank - different.esp"); EXPECT_EQ("Blank - Different.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -362,8 +362,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0xD4C9B7AE, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - master dependent.esp")); - plugin = game.plugins.find("blank - master dependent.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esp")); + plugin = game.GetPlugin("blank - master dependent.esp"); EXPECT_EQ("Blank - Master Dependent.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -380,8 +380,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0x832152DC, plugin.Crc()); EXPECT_EQ(2, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different master dependent.esp")); - plugin = game.plugins.find("blank - different master dependent.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esp")); + plugin = game.GetPlugin("blank - different master dependent.esp"); EXPECT_EQ("Blank - Different Master Dependent.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -397,8 +397,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0x3AD17683, plugin.Crc()); EXPECT_EQ(2, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - plugin dependent.esp")); - plugin = game.plugins.find("blank - plugin dependent.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - plugin dependent.esp")); + plugin = game.GetPlugin("blank - plugin dependent.esp"); EXPECT_EQ("Blank - Plugin Dependent.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -413,8 +413,8 @@ TEST_F(Game, LoadPlugins) { EXPECT_EQ(0x28EF26DB, plugin.Crc()); EXPECT_EQ(1, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different plugin dependent.esp")); - plugin = game.plugins.find("blank - different plugin dependent.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - different plugin dependent.esp")); + plugin = game.GetPlugin("blank - different plugin dependent.esp"); EXPECT_EQ("Blank - Different Plugin Dependent.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -434,11 +434,11 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { game.SetGamePath(dataPath.parent_path()); EXPECT_NO_THROW(game.LoadPlugins(true)); - EXPECT_EQ(11, game.plugins.size()); + EXPECT_EQ(11, game.GetPlugins().size()); // Check that all the plugins' data have loaded correctly. - ASSERT_NE(game.plugins.end(), game.plugins.find("skyrim.esm")); - loot::Plugin plugin = game.plugins.find("skyrim.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("Skyrim.esm")); + loot::Plugin plugin = game.GetPlugin("Skyrim.esm"); EXPECT_EQ("Skyrim.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -448,8 +448,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank.esm")); - plugin = game.plugins.find("blank.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("blank.esm")); + plugin = game.GetPlugin("blank.esm"); EXPECT_EQ("Blank.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -459,8 +459,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different.esm")); - plugin = game.plugins.find("blank - different.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("Blank - Different.esm")); + plugin = game.GetPlugin("Blank - Different.esm"); EXPECT_EQ("Blank - Different.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -470,8 +470,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - master dependent.esm")); - plugin = game.plugins.find("blank - master dependent.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esm")); + plugin = game.GetPlugin("blank - master dependent.esm"); EXPECT_EQ("Blank - Master Dependent.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -483,8 +483,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different master dependent.esm")); - plugin = game.plugins.find("blank - different master dependent.esm")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esm")); + plugin = game.GetPlugin("blank - different master dependent.esm"); EXPECT_EQ("Blank - Different Master Dependent.esm", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_TRUE(plugin.isMasterFile()); @@ -496,8 +496,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank.esp")); - plugin = game.plugins.find("blank.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank.esp")); + plugin = game.GetPlugin("blank.esp"); EXPECT_EQ("Blank.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -507,8 +507,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different.esp")); - plugin = game.plugins.find("blank - different.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - different.esp")); + plugin = game.GetPlugin("blank - different.esp"); EXPECT_EQ("Blank - Different.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -518,8 +518,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - master dependent.esp")); - plugin = game.plugins.find("blank - master dependent.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - master dependent.esp")); + plugin = game.GetPlugin("blank - master dependent.esp"); EXPECT_EQ("Blank - Master Dependent.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -531,8 +531,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different master dependent.esp")); - plugin = game.plugins.find("blank - different master dependent.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - different master dependent.esp")); + plugin = game.GetPlugin("blank - different master dependent.esp"); EXPECT_EQ("Blank - Different Master Dependent.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -544,8 +544,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - plugin dependent.esp")); - plugin = game.plugins.find("blank - plugin dependent.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - plugin dependent.esp")); + plugin = game.GetPlugin("blank - plugin dependent.esp"); EXPECT_EQ("Blank - Plugin Dependent.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); @@ -557,8 +557,8 @@ TEST_F(Game, LoadPlugins_HeadersOnly) { EXPECT_EQ(0, plugin.Crc()); EXPECT_EQ(0, plugin.NumOverrideFormIDs()); - ASSERT_NE(game.plugins.end(), game.plugins.find("blank - different plugin dependent.esp")); - plugin = game.plugins.find("blank - different plugin dependent.esp")->second; + ASSERT_NO_THROW(game.GetPlugin("blank - different plugin dependent.esp")); + plugin = game.GetPlugin("blank - different plugin dependent.esp"); EXPECT_EQ("Blank - Different Plugin Dependent.esp", plugin.Name()); EXPECT_FALSE(plugin.IsEmpty()); EXPECT_FALSE(plugin.isMasterFile()); diff --git a/src/tests/backend/test_plugin_sorter.h b/src/tests/backend/test_plugin_sorter.h index 8cb04b69..9d25dc3f 100644 --- a/src/tests/backend/test_plugin_sorter.h +++ b/src/tests/backend/test_plugin_sorter.h @@ -94,7 +94,7 @@ TEST_F(PluginSorter, Sort_WithPriority) { ASSERT_NO_THROW(game.LoadPlugins(false)); loot::PluginMetadata plugin("Blank - Different Master Dependent.esp"); plugin.Priority(-1100000); - game.userlist.AddPlugin(plugin); + game.GetUserlist().AddPlugin(plugin); loot::PluginSorter ps; std::list expectedSortedOrder({ @@ -122,7 +122,7 @@ TEST_F(PluginSorter, Sort_WithLoadAfter) { loot::File("Blank - Different.esp"), loot::File("Blank - Different Plugin Dependent.esp"), }); - game.userlist.AddPlugin(plugin); + game.GetUserlist().AddPlugin(plugin); loot::PluginSorter ps; std::list expectedSortedOrder({ @@ -150,7 +150,7 @@ TEST_F(PluginSorter, Sort_WithRequirements) { loot::File("Blank - Different.esp"), loot::File("Blank - Different Plugin Dependent.esp"), }); - game.userlist.AddPlugin(plugin); + game.GetUserlist().AddPlugin(plugin); loot::PluginSorter ps; std::list expectedSortedOrder({ @@ -175,7 +175,7 @@ TEST_F(PluginSorter, Sort_HasCycle) { ASSERT_NO_THROW(game.LoadPlugins(false)); loot::PluginMetadata plugin("Blank.esm"); plugin.LoadAfter({loot::File("Blank - Master Dependent.esm")}); - game.userlist.AddPlugin(plugin); + game.GetUserlist().AddPlugin(plugin); loot::PluginSorter ps; EXPECT_ANY_THROW(ps.Sort(game, loot::Language::english, callback));