diff --git a/src/backend/game.cpp b/src/backend/game.cpp index 0b5b22c1..f9164d5c 100644 --- a/src/backend/game.cpp +++ b/src/backend/game.cpp @@ -362,10 +362,6 @@ namespace loot { } } - bool Game::IsActive(const std::string& plugin) const { - return activePlugins.find(boost::locale::to_lower(plugin)) != activePlugins.end(); - } - void Game::GetLoadOrder(std::list& loadOrder) const { BOOST_LOG_TRIVIAL(debug) << "Getting load order for game: " << _name; @@ -486,7 +482,7 @@ namespace loot { //First calculate the mean plugin size. Store it temporarily in a map to reduce filesystem lookups and file size recalculation. BOOST_LOG_TRIVIAL(trace) << "Scanning for plugins in " << this->DataPath(); for (fs::directory_iterator it(this->DataPath()); it != fs::directory_iterator(); ++it) { - if (fs::is_regular_file(it->status()) && this->IsValidPlugin(it->path().filename().string())) { + if (fs::is_regular_file(it->status()) && Plugin(it->path().filename().string()).IsValid(*this)) { uintmax_t fileSize = fs::file_size(it->path()); meanFileSize += fileSize; @@ -551,37 +547,6 @@ namespace loot { return false; } - bool Game::IsValidPlugin(const std::string& name) const { - BOOST_LOG_TRIVIAL(trace) << "Checking to see if \"" << name << "\" is a valid plugin."; - // Rather than just checking the extension, try also parsing the file header, and see if it fails. - if (!boost::iends_with(name, ".esm") && !boost::iends_with(name, ".esp") && !boost::iends_with(name, ".esm.ghost") && !boost::iends_with(name, ".esp.ghost")) { - return false; - } - - try { - string filepath = (this->DataPath() / name).string(); - if (fs::exists(this->DataPath() / fs::path(name + ".ghost"))) - filepath += ".ghost"; - - espm::File * file = nullptr; - if (this->Id() == LIBLO_GAME_TES4) - file = new espm::tes4::File(filepath, this->espm_settings, false, true); - else if (this->Id() == LIBLO_GAME_TES5) - file = new espm::tes5::File(filepath, this->espm_settings, false, true); - else if (this->Id() == LIBLO_GAME_FO3) - file = new espm::fo3::File(filepath, this->espm_settings, false, true); - else - file = new espm::fonv::File(filepath, this->espm_settings, false, true); - - delete file; - } - catch (std::exception& /*e*/) { - BOOST_LOG_TRIVIAL(warning) << "The .es(p|m) file \"" << name << "\" is not a valid plugin."; - return false; - } - return true; - } - void Game::CreateLOOTGameFolder() { //Make sure that the LOOT game path exists. try { diff --git a/src/backend/game.h b/src/backend/game.h index 417d7e13..8f0f8b03 100644 --- a/src/backend/game.h +++ b/src/backend/game.h @@ -73,9 +73,6 @@ namespace loot { boost::filesystem::path MasterlistPath() const; boost::filesystem::path UserlistPath() const; - //Game plugin functions. - 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 SetLoadOrder(const char * const * const loadOrder, const size_t numPlugins) const; // For API. @@ -85,13 +82,12 @@ namespace loot { void LoadPlugins(bool headersOnly); //Loads all installed plugins. bool HasBeenLoaded(); // Checks if the game's plugins have already been loaded. - bool IsValidPlugin(const std::string& name) const; - std::list Sort(const unsigned int language, std::function progressCallback); //Caches for condition results, active plugins and CRCs. std::unordered_map conditionCache; //Holds lowercased strings. std::unordered_map crcCache; //Holds lowercased strings. + std::unordered_set activePlugins; //Holds lowercased strings. //Plugin data and metadata lists. Masterlist masterlist; @@ -119,8 +115,6 @@ namespace loot { boost::filesystem::path gamePath; //Path to the game's folder. boost::filesystem::path _gameLocalDataPath; // Path to the game's folder in %LOCALAPPDATA%. - std::unordered_set activePlugins; //Holds lowercased strings. - lo_game_handle gh; //Creates directory in LOOT folder for LOOT's game-specific files. diff --git a/src/backend/metadata/condition_grammar.h b/src/backend/metadata/condition_grammar.h index dad8a648..8c7f9c70 100644 --- a/src/backend/metadata/condition_grammar.h +++ b/src/backend/metadata/condition_grammar.h @@ -292,7 +292,7 @@ namespace loot { Version trueVersion; if (file == "LOOT") trueVersion = Version(boost::filesystem::absolute("LOOT.exe")); - else if (_game->IsValidPlugin(file)) { + else if (Plugin(file).IsValid(*_game)) { Plugin plugin(*_game, file, true); trueVersion = Version(plugin.Version()); } @@ -319,7 +319,7 @@ namespace loot { if (file == "LOOT") result = false; else - result = _game->IsActive(file); + result = Plugin(file).IsActive(*_game); BOOST_LOG_TRIVIAL(trace) << "Active check result: " << result; } diff --git a/src/backend/plugin.cpp b/src/backend/plugin.cpp index 0a20a45c..c59c9a4e 100644 --- a/src/backend/plugin.cpp +++ b/src/backend/plugin.cpp @@ -214,6 +214,42 @@ namespace loot { return _isEmpty; } + bool Plugin::IsValid(const Game& game) const { + BOOST_LOG_TRIVIAL(trace) << "Checking to see if \"" << name << "\" is a valid plugin."; + // Rather than just checking the extension, try also parsing the file header, and see if it fails. + if (!boost::iends_with(name, ".esm") && !boost::iends_with(name, ".esp")) { + return false; + } + + try { + boost::filesystem::path filepath = game.DataPath() / name; + //In case the plugin is ghosted. + if (!boost::filesystem::exists(filepath) && boost::filesystem::exists(filepath.string() + ".ghost")) + filepath += ".ghost"; + + espm::File * file = nullptr; + if (game.Id() == Game::tes4) + file = new espm::tes4::File(filepath, game.espm_settings, false, true); + else if (game.Id() == Game::tes5) + file = new espm::tes5::File(filepath, game.espm_settings, false, true); + else if (game.Id() == Game::fo3) + file = new espm::fo3::File(filepath, game.espm_settings, false, true); + else + file = new espm::fonv::File(filepath, game.espm_settings, false, true); + + delete file; + } + catch (std::exception& /*e*/) { + BOOST_LOG_TRIVIAL(warning) << "The .es(p|m) file \"" << name << "\" is not a valid plugin."; + return false; + } + return true; + } + + bool Plugin::IsActive(const Game& game) const { + return game.activePlugins.find(boost::locale::to_lower(name)) != game.activePlugins.end(); + } + std::string Plugin::Version() const { return version; } @@ -225,7 +261,7 @@ namespace loot { bool Plugin::CheckInstallValidity(const Game& game) { BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to " << name << "'s data."; unsigned int messageType; - if (game.IsActive(name)) + if (IsActive(game)) messageType = loot::Message::error; else messageType = loot::Message::warn; @@ -235,7 +271,7 @@ namespace loot { BOOST_LOG_TRIVIAL(error) << "\"" << name << "\" requires \"" << master << "\", but it is missing."; messages.push_back(loot::Message(messageType, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be installed, but it is missing.")) % master).str())); } - else if (!game.IsActive(master)) { + else if (!Plugin(master).IsActive(game)) { BOOST_LOG_TRIVIAL(error) << "\"" << name << "\" requires \"" << master << "\", but it is inactive."; messages.push_back(loot::Message(messageType, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be active, but it is inactive.")) % master).str())); } @@ -249,7 +285,7 @@ namespace loot { } for (const auto &inc : incompatibilities) { if (boost::filesystem::exists(game.DataPath() / inc.Name()) || ((boost::iends_with(inc.Name(), ".esp") || boost::iends_with(inc.Name(), ".esm")) && boost::filesystem::exists(game.DataPath() / (inc.Name() + ".ghost")))) { - if (!game.IsActive(inc.Name())) + if (!Plugin(inc.Name()).IsActive(game)) messageType = loot::Message::warn; BOOST_LOG_TRIVIAL(error) << "\"" << name << "\" is incompatible with \"" << inc.Name() << "\", but both are present."; messages.push_back(loot::Message(messageType, (boost::format(boost::locale::translate("This plugin is incompatible with \"%1%\", but both are present.")) % inc.Name()).str())); diff --git a/src/backend/plugin.h b/src/backend/plugin.h index 19c52199..4aa2f1dc 100644 --- a/src/backend/plugin.h +++ b/src/backend/plugin.h @@ -52,6 +52,8 @@ namespace loot { uint32_t Crc() const; bool LoadsBSA(const Game& game) const; + bool IsValid(const Game& game) const; + bool IsActive(const Game& game) const; //Compare name strings. bool operator == (const Plugin& rhs) const; diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index d81ec597..3c913c78 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -333,7 +333,7 @@ namespace loot { } size_t i = 0; for (const auto& plugin : plugins) { - if (_lootState.CurrentGame().IsActive(plugin)) { + if (Plugin(plugin).IsActive(_lootState.CurrentGame())) { ss << setw(decLength) << i << " " << hex << setw(2) << i << dec << " "; ++i; } @@ -709,7 +709,7 @@ namespace loot { pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object. pluginNode["name"] = plugin.Name(); - pluginNode["isActive"] = _lootState.CurrentGame().IsActive(plugin.Name()); + pluginNode["isActive"] = plugin.IsActive(_lootState.CurrentGame()); pluginNode["isEmpty"] = plugin.IsEmpty(); pluginNode["isMaster"] = plugin.IsMaster(); pluginNode["loadsBSA"] = plugin.LoadsBSA(_lootState.CurrentGame());