diff --git a/src/backend/game/game.cpp b/src/backend/game/game.cpp index 67fea97b..930ae034 100644 --- a/src/backend/game/game.cpp +++ b/src/backend/game/game.cpp @@ -208,6 +208,14 @@ namespace loot { return _pluginsFullyLoaded; } + 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 + return LoadOrderHandler::IsPluginActive(pluginName); + } + void Game::addPlugin(const Plugin&& plugin) { std::lock_guard lock(mutex); plugins.emplace(boost::locale::to_lower(plugin.Name()), plugin); diff --git a/src/backend/game/game.h b/src/backend/game/game.h index 92a78638..4b3afd07 100644 --- a/src/backend/game/game.h +++ b/src/backend/game/game.h @@ -55,6 +55,10 @@ namespace loot { void LoadPlugins(bool headersOnly); //Loads all installed plugins. bool ArePluginsFullyLoaded() const; // Checks if the game's plugins have already been loaded. + // 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; diff --git a/src/backend/metadata/condition_grammar.h b/src/backend/metadata/condition_grammar.h index 39c46354..3f29628a 100644 --- a/src/backend/metadata/condition_grammar.h +++ b/src/backend/metadata/condition_grammar.h @@ -363,7 +363,7 @@ namespace loot { if (file == "LOOT") result = false; else - result = Plugin(*_game, file, true).IsActive(); + result = _game->IsPluginActive(file); BOOST_LOG_TRIVIAL(trace) << "Active check result: " << result; } diff --git a/src/backend/plugin/plugin.cpp b/src/backend/plugin/plugin.cpp index 63c9af7b..c94a1318 100644 --- a/src/backend/plugin/plugin.cpp +++ b/src/backend/plugin/plugin.cpp @@ -205,7 +205,7 @@ namespace loot { BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" requires \"" << master << "\", but it is missing."; messages.push_back(Message(Message::error, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be installed, but it is missing.")) % master).str())); } - else if (!Plugin(game, master, true).IsActive()) { + else if (!game.IsPluginActive(master)) { BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" requires \"" << master << "\", but it is inactive."; messages.push_back(Message(Message::error, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be active, but it is inactive.")) % master).str())); } @@ -219,7 +219,7 @@ namespace loot { } } for (const auto &inc : Incs()) { - if (pluginExists(game, inc.Name()) && Plugin(game, inc.Name(), true).IsActive()) { + if (pluginExists(game, inc.Name()) && game.IsPluginActive(inc.Name())) { BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" is incompatible with \"" << inc.Name() << "\", but both are present."; messages.push_back(loot::Message(Message::error, (boost::format(boost::locale::translate("This plugin is incompatible with \"%1%\", but both are present.")) % inc.Name()).str())); } diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 6c3642cb..e30c7a2e 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -354,15 +354,15 @@ namespace loot { decLength = 2; } size_t i = 0; - for (const auto& plugin : plugins) { - if (Plugin(_lootState.CurrentGame(), plugin, true).IsActive()) { + for (const auto& pluginName : plugins) { + if (_lootState.CurrentGame().IsPluginActive(pluginName)) { ss << setw(decLength) << i << " " << hex << setw(2) << i << dec << " "; ++i; } else { ss << setw(decLength + 4) << " "; } - ss << plugin << "\r\n"; + ss << pluginName << "\r\n"; } CopyToClipboard(ss.str()); callback->Success(""); diff --git a/src/tests/backend/game/test_game.h b/src/tests/backend/game/test_game.h index 178a39a0..3a1157d7 100644 --- a/src/tests/backend/game/test_game.h +++ b/src/tests/backend/game/test_game.h @@ -580,6 +580,81 @@ TEST_F(Game, ArePluginsFullyLoaded) { EXPECT_TRUE(game.ArePluginsFullyLoaded()); } +TEST_F(Game, shouldThrowIfCheckingIfPluginThatIsntLoadedIsActiveAndGameHasNotBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + + EXPECT_ANY_THROW(game.IsPluginActive("Blank.esm")); +} + +TEST_F(Game, shouldShowBlankEsmAsActiveIfItHasNotBeenLoadedAndTheGameHasBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + + EXPECT_TRUE(game.IsPluginActive("Blank.esm")); +} + +TEST_F(Game, shouldShowBlankEspAsInctiveIfItHasNotBeenLoadedAndTheGameHasBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + + EXPECT_FALSE(game.IsPluginActive("Blank.esp")); +} + +TEST_F(Game, shouldShowBlankEsmAsInactiveIfItsHeaderHasBeenLoadedAndGameHasNotBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_FALSE(game.IsPluginActive("Blank.esm")); +} + +TEST_F(Game, shouldShowBlankEspAsActiveIfItsHeaderHasBeenLoadedAndGameHasNotBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_FALSE(game.IsPluginActive("Blank.esp")); +} + +TEST_F(Game, shouldShowBlankEsmAsActiveIfItsHeaderHasBeenLoadedAndTheGameHasBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_TRUE(game.IsPluginActive("Blank.esm")); +} + +TEST_F(Game, shouldShowBlankEspAsActiveIfItsHeaderHasBeenLoadedAndTheGameHasBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(true)); + + EXPECT_FALSE(game.IsPluginActive("Blank.esp")); +} + +TEST_F(Game, shouldShowBlankEsmAsActiveIfItHasBeenFullyLoadedAndTheGameHasBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(false)); + + EXPECT_TRUE(game.IsPluginActive("Blank.esm")); +} + +TEST_F(Game, shouldShowBlankEspAsActiveIfItHasBeenFullyLoadedAndTheGameHasBeenInitialised) { + loot::Game game(loot::Game::tes5); + game.SetGamePath(dataPath.parent_path()); + ASSERT_NO_THROW(game.Init(false, localPath)); + ASSERT_NO_THROW(game.LoadPlugins(false)); + + EXPECT_FALSE(game.IsPluginActive("Blank.esp")); +} + TEST(ToGames, EmptySettings) { EXPECT_EQ(std::list(), loot::ToGames(std::list())); }