mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Remove active plugins from game cache
Cache them in the Plugin objects instead.
This commit is contained in:
@@ -400,7 +400,6 @@ LOOT_API unsigned int loot_eval_lists(loot_db db, const unsigned int language) {
|
||||
loot::MetadataList userTemp = db->rawUserMetadata;
|
||||
try {
|
||||
// Refresh active plugins before evaluating conditions.
|
||||
db->RefreshActivePluginsList();
|
||||
temp.EvalAllConditions(*db, language);
|
||||
userTemp.EvalAllConditions(*db, language);
|
||||
}
|
||||
|
||||
@@ -77,12 +77,6 @@ namespace loot {
|
||||
}
|
||||
|
||||
LoadOrderHandler::Init(*this, gameLocalAppData);
|
||||
|
||||
RefreshActivePluginsList();
|
||||
}
|
||||
|
||||
void Game::RefreshActivePluginsList() {
|
||||
CacheActivePlugins(GetActivePlugins());
|
||||
}
|
||||
|
||||
void Game::RedatePlugins() {
|
||||
|
||||
@@ -47,7 +47,6 @@ namespace loot {
|
||||
|
||||
void Init(bool createFolder, const boost::filesystem::path& gameLocalAppData = "");
|
||||
|
||||
void RefreshActivePluginsList();
|
||||
void RedatePlugins(); //Change timestamps to match load order (Skyrim only).
|
||||
|
||||
void LoadPlugins(bool headersOnly); //Loads all installed plugins.
|
||||
|
||||
@@ -41,12 +41,10 @@ namespace lc = boost::locale;
|
||||
namespace loot {
|
||||
GameCache::GameCache() {}
|
||||
GameCache::GameCache(const GameCache& cache)
|
||||
: conditionCache(cache.conditionCache),
|
||||
activePlugins(cache.activePlugins) {}
|
||||
: conditionCache(cache.conditionCache) {}
|
||||
|
||||
GameCache& GameCache::operator=(const GameCache& cache) {
|
||||
conditionCache = cache.conditionCache;
|
||||
activePlugins = cache.activePlugins;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -56,11 +54,6 @@ namespace loot {
|
||||
conditionCache.insert(pair<string, bool>(boost::locale::to_lower(condition), result));
|
||||
}
|
||||
|
||||
void GameCache::CacheActivePlugins(const std::unordered_set<std::string>& plugins) {
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
activePlugins = plugins;
|
||||
}
|
||||
|
||||
std::pair<bool, bool> GameCache::GetCachedCondition(const std::string& condition) const {
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
@@ -72,16 +65,9 @@ namespace loot {
|
||||
return std::pair<bool, bool>(false, false);
|
||||
}
|
||||
|
||||
bool GameCache::IsPluginActive(const std::string& plugin) const {
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
return activePlugins.find(boost::locale::to_lower(plugin)) != activePlugins.end();
|
||||
}
|
||||
|
||||
void GameCache::ClearCache() {
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
conditionCache.clear();
|
||||
activePlugins.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,17 +40,14 @@ namespace loot {
|
||||
GameCache& operator=(const GameCache& cache);
|
||||
|
||||
void CacheCondition(const std::string& condition, bool result);
|
||||
void CacheActivePlugins(const std::unordered_set<std::string>& plugins);
|
||||
|
||||
// Returns false for second bool if no cached condition.
|
||||
std::pair<bool, bool> GetCachedCondition(const std::string& condition) const;
|
||||
bool IsPluginActive(const std::string& plugin) const;
|
||||
|
||||
void ClearCache();
|
||||
private:
|
||||
//Caches for condition results, CRCs and active plugins.
|
||||
std::unordered_map<std::string, bool> conditionCache;
|
||||
std::unordered_set<std::string> activePlugins;
|
||||
|
||||
mutable std::mutex mutex;
|
||||
};
|
||||
|
||||
@@ -97,33 +97,28 @@ namespace loot {
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> LoadOrderHandler::GetActivePlugins() const {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Getting active plugins.";
|
||||
bool LoadOrderHandler::IsPluginActive(const std::string& pluginName) const {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Checking if plugin \"" << pluginName << "\" is active.";
|
||||
|
||||
char ** pluginArr;
|
||||
size_t pluginArrSize;
|
||||
unsigned int ret = lo_get_active_plugins(_gh, &pluginArr, &pluginArrSize);
|
||||
if (ret != LIBLO_OK && ret != LIBLO_WARN_BAD_FILENAME && ret != LIBLO_WARN_INVALID_LIST && ret != LIBLO_WARN_LO_MISMATCH) {
|
||||
bool result = false;
|
||||
unsigned int ret = lo_get_plugin_active(_gh, pluginName.c_str(), &result);
|
||||
if (ret != LIBLO_OK && ret != LIBLO_WARN_BAD_FILENAME) {
|
||||
const char * e = nullptr;
|
||||
string err;
|
||||
lo_get_error_message(&e);
|
||||
if (e == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(error) << "libloadorder failed to get the active plugins list. Details could not be fetched.";
|
||||
err = lc::translate("libloadorder failed to get the active plugins list. Details could not be fetched.").str();
|
||||
BOOST_LOG_TRIVIAL(error) << "libloadorder failed to check if a plugin is active. Details could not be fetched.";
|
||||
err = lc::translate("libloadorder failed to check if a plugin is active. Details could not be fetched.").str();
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(error) << "libloadorder failed to get the active plugins list. Details: " << e;
|
||||
err = lc::translate("libloadorder failed to get the active plugins list. Details:").str() + " " + e;
|
||||
BOOST_LOG_TRIVIAL(error) << "libloadorder failed to check if a plugin is active. Details: " << e;
|
||||
err = lc::translate("libloadorder failed to check if a plugin is active. Details:").str() + " " + e;
|
||||
}
|
||||
lo_cleanup();
|
||||
throw error(error::liblo_error, err);
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> activePlugins;
|
||||
for (size_t i = 0; i < pluginArrSize; ++i) {
|
||||
activePlugins.insert(boost::locale::to_lower(string(pluginArr[i])));
|
||||
}
|
||||
return activePlugins;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::list<std::string> LoadOrderHandler::GetLoadOrder() const {
|
||||
|
||||
@@ -43,9 +43,10 @@ namespace loot {
|
||||
|
||||
void Init(const GameSettings& game, const boost::filesystem::path& gameLocalAppData = "");
|
||||
|
||||
std::unordered_set<std::string> GetActivePlugins() const;
|
||||
std::list<std::string> GetLoadOrder() const;
|
||||
|
||||
bool IsPluginActive(const std::string& pluginName) const;
|
||||
|
||||
//These modify game load order, even though const.
|
||||
void SetLoadOrder(const char * const * const loadOrder, const size_t numPlugins) const; // For API.
|
||||
void SetLoadOrder(const std::list<std::string>& loadOrder) const;
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace loot {
|
||||
if (file == "LOOT")
|
||||
result = false;
|
||||
else
|
||||
result = Plugin(file).IsActive(*_game);
|
||||
result = Plugin(*_game, file, true).IsActive();
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "Active check result: " << result;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace loot {
|
||||
PluginMetadata(n),
|
||||
libespm::Plugin(libespm::GameId::SKYRIM),
|
||||
_isEmpty(true),
|
||||
_isActive(false),
|
||||
_loadsBsa(false),
|
||||
crc(0),
|
||||
numOverrideRecords(0) {}
|
||||
@@ -50,6 +51,7 @@ namespace loot {
|
||||
PluginMetadata(name),
|
||||
libespm::Plugin(game.LibespmId()),
|
||||
_isEmpty(true),
|
||||
_isActive(false),
|
||||
_loadsBsa(false),
|
||||
crc(0),
|
||||
numOverrideRecords(0) {
|
||||
@@ -96,6 +98,8 @@ namespace loot {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get whether the plugin is active or not.
|
||||
_isActive = game.IsPluginActive(name);
|
||||
|
||||
// Get whether the plugin loads a BSA or not.
|
||||
if (game.Id() == Game::tes5) {
|
||||
@@ -192,8 +196,8 @@ namespace loot {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Plugin::IsActive(const Game& game) const {
|
||||
return game.IsPluginActive(Name());
|
||||
bool Plugin::IsActive() const {
|
||||
return _isActive;
|
||||
}
|
||||
|
||||
uint32_t Plugin::Crc() const {
|
||||
@@ -202,7 +206,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.";
|
||||
if (IsActive(game)) {
|
||||
if (IsActive()) {
|
||||
auto pluginExists = [](const Game& game, const std::string& file) {
|
||||
return boost::filesystem::exists(game.DataPath() / file)
|
||||
|| ((boost::iends_with(file, ".esp") || boost::iends_with(file, ".esm")) && boost::filesystem::exists(game.DataPath() / (file + ".ghost")));
|
||||
@@ -213,7 +217,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(master).IsActive(game)) {
|
||||
else if (!Plugin(game, master, true).IsActive()) {
|
||||
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()));
|
||||
}
|
||||
@@ -227,7 +231,7 @@ namespace loot {
|
||||
}
|
||||
}
|
||||
for (const auto &inc : Incs()) {
|
||||
if (pluginExists(game, inc.Name()) && Plugin(inc.Name()).IsActive(game)) {
|
||||
if (pluginExists(game, inc.Name()) && Plugin(game, inc.Name(), true).IsActive()) {
|
||||
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()));
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace loot {
|
||||
size_t NumOverrideFormIDs() const;
|
||||
|
||||
bool LoadsBSA() const;
|
||||
bool IsActive(const Game& game) const;
|
||||
bool IsActive() const;
|
||||
|
||||
//Load ordering functions.
|
||||
bool DoFormIDsOverlap(const Plugin& plugin) const;
|
||||
@@ -65,6 +65,7 @@ namespace loot {
|
||||
static bool IsValid(const std::string& filename, const Game& game);
|
||||
private:
|
||||
bool _isEmpty; // Does the plugin contain any records other than the TES4 header?
|
||||
bool _isActive;
|
||||
bool _loadsBsa;
|
||||
std::string version; //Obtained from description field.
|
||||
uint32_t crc;
|
||||
|
||||
+2
-5
@@ -355,7 +355,7 @@ namespace loot {
|
||||
}
|
||||
size_t i = 0;
|
||||
for (const auto& plugin : plugins) {
|
||||
if (Plugin(plugin).IsActive(_lootState.CurrentGame())) {
|
||||
if (Plugin(_lootState.CurrentGame(), plugin, true).IsActive()) {
|
||||
ss << setw(decLength) << i << " " << hex << setw(2) << i << dec << " ";
|
||||
++i;
|
||||
}
|
||||
@@ -642,9 +642,6 @@ namespace loot {
|
||||
// First clear CRC and condition caches, otherwise they could lead to incorrect evaluations.
|
||||
_lootState.CurrentGame().ClearCache();
|
||||
|
||||
// Also refresh active plugins list.
|
||||
_lootState.CurrentGame().RefreshActivePluginsList();
|
||||
|
||||
bool isFirstLoad = _lootState.CurrentGame().plugins.empty();
|
||||
_lootState.CurrentGame().LoadPlugins(true);
|
||||
|
||||
@@ -741,7 +738,7 @@ namespace loot {
|
||||
|
||||
pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object.
|
||||
pluginNode["name"] = plugin.Name();
|
||||
pluginNode["isActive"] = plugin.IsActive(_lootState.CurrentGame());
|
||||
pluginNode["isActive"] = plugin.IsActive();
|
||||
pluginNode["isEmpty"] = plugin.IsEmpty();
|
||||
pluginNode["isMaster"] = plugin.isMasterFile();
|
||||
pluginNode["loadsBSA"] = plugin.LoadsBSA();
|
||||
|
||||
@@ -133,33 +133,8 @@ TEST_F(Game, Init) {
|
||||
ASSERT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName()));
|
||||
EXPECT_THROW(game.Init(false), loot::error);
|
||||
EXPECT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName()));
|
||||
EXPECT_FALSE(game.IsPluginActive("Skyrim.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("skyrim.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Plugin Dependent.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different Plugin Dependent.esp"));
|
||||
|
||||
game = loot::Game(loot::Game::tes5).SetGamePath(dataPath.parent_path());
|
||||
EXPECT_FALSE(game.IsPluginActive("Skyrim.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("skyrim.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Plugin Dependent.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different Plugin Dependent.esp"));
|
||||
|
||||
EXPECT_NO_THROW(game.Init(false, localPath));
|
||||
EXPECT_FALSE(boost::filesystem::exists(loot::g_path_local / game.FolderName()));
|
||||
EXPECT_TRUE(game.IsPluginActive("Skyrim.esm"));
|
||||
@@ -200,32 +175,6 @@ TEST_F(Game, Init) {
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(Game, RefreshActivePluginsList) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
|
||||
// Throw because the load order handler hasn't been initialised.
|
||||
EXPECT_THROW(game.RefreshActivePluginsList(), loot::error);
|
||||
|
||||
// Calling Init calls RefreshActivePluginsList, so clear it before testing
|
||||
// separately.
|
||||
game.Init(false, localPath);
|
||||
EXPECT_NO_THROW(game.ClearCache());
|
||||
EXPECT_NO_THROW(game.RefreshActivePluginsList());
|
||||
EXPECT_TRUE(game.IsPluginActive("Skyrim.esm"));
|
||||
EXPECT_TRUE(game.IsPluginActive("skyrim.esm"));
|
||||
EXPECT_TRUE(game.IsPluginActive("Blank.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different Master Dependent.esm"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Master Dependent.esp"));
|
||||
EXPECT_TRUE(game.IsPluginActive("Blank - Different Master Dependent.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Plugin Dependent.esp"));
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank - Different Plugin Dependent.esp"));
|
||||
}
|
||||
|
||||
TEST_F(Game, RedatePlugins) {
|
||||
loot::Game game(loot::Game::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
|
||||
@@ -36,11 +36,9 @@ TEST_F(GameCache, Constructors) {
|
||||
std::unordered_set<std::string> plugins({"skyrim.esm"});
|
||||
|
||||
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
|
||||
EXPECT_NO_THROW(cache.CacheActivePlugins(plugins));
|
||||
|
||||
loot::GameCache cache2(cache);
|
||||
EXPECT_EQ(std::make_pair(true, true), cache2.GetCachedCondition("true Condition"));
|
||||
EXPECT_TRUE(cache2.IsPluginActive("Skyrim.esm"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, AssignmentOperator) {
|
||||
@@ -48,11 +46,9 @@ TEST_F(GameCache, AssignmentOperator) {
|
||||
std::unordered_set<std::string> plugins({"skyrim.esm"});
|
||||
|
||||
EXPECT_NO_THROW(cache.CacheCondition("True Condition", true));
|
||||
EXPECT_NO_THROW(cache.CacheActivePlugins(plugins));
|
||||
|
||||
loot::GameCache cache2 = cache;
|
||||
EXPECT_EQ(std::make_pair(true, true), cache2.GetCachedCondition("true Condition"));
|
||||
EXPECT_TRUE(cache2.IsPluginActive("Skyrim.esm"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, CacheCondition) {
|
||||
@@ -67,19 +63,6 @@ TEST_F(GameCache, CacheCondition) {
|
||||
EXPECT_EQ(std::make_pair(false, false), cache.GetCachedCondition("false missing Condition"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, CacheActivePlugins) {
|
||||
loot::GameCache cache;
|
||||
std::unordered_set<std::string> plugins({
|
||||
"skyrim.esm",
|
||||
"blank.esp"
|
||||
});
|
||||
EXPECT_NO_THROW(cache.CacheActivePlugins(plugins));
|
||||
|
||||
EXPECT_TRUE(cache.IsPluginActive("Skyrim.esm"));
|
||||
EXPECT_TRUE(cache.IsPluginActive("Blank.esp"));
|
||||
EXPECT_FALSE(cache.IsPluginActive("Blank.missing.esp"));
|
||||
}
|
||||
|
||||
TEST_F(GameCache, ClearCache) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,19 +66,19 @@ TEST_F(LoadOrderHandler, Init) {
|
||||
EXPECT_NO_THROW(loh.Init(game, localPath));
|
||||
}
|
||||
|
||||
TEST_F(LoadOrderHandler, GetActivePlugins) {
|
||||
TEST_F(LoadOrderHandler, IsPluginActive) {
|
||||
loot::LoadOrderHandler loh;
|
||||
loot::GameSettings game(loot::GameSettings::tes5);
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
|
||||
EXPECT_THROW(loh.IsPluginActive("Skyrim.esm"), loot::error);
|
||||
|
||||
ASSERT_NO_THROW(loh.Init(game, localPath));
|
||||
|
||||
std::unordered_set<std::string> expected({
|
||||
"skyrim.esm",
|
||||
"blank.esm",
|
||||
"blank - different master dependent.esp",
|
||||
});
|
||||
|
||||
EXPECT_EQ(expected, loh.GetActivePlugins());
|
||||
EXPECT_TRUE(loh.IsPluginActive("Skyrim.esm"));
|
||||
EXPECT_TRUE(loh.IsPluginActive("Blank.esm"));
|
||||
EXPECT_TRUE(loh.IsPluginActive("Blank - Different Master Dependent.esp"));
|
||||
EXPECT_FALSE(loh.IsPluginActive("Blank.esp"));
|
||||
}
|
||||
|
||||
TEST_F(LoadOrderHandler, GetLoadOrder) {
|
||||
|
||||
@@ -116,11 +116,11 @@ TEST_F(Plugin, IsActive) {
|
||||
game.SetGamePath(dataPath.parent_path());
|
||||
ASSERT_NO_THROW(game.Init(false, localPath));
|
||||
|
||||
loot::Plugin plugin("Blank.esm");
|
||||
EXPECT_TRUE(plugin.IsActive(game));
|
||||
loot::Plugin plugin(game, "Blank.esm", true);
|
||||
EXPECT_TRUE(plugin.IsActive());
|
||||
|
||||
plugin = loot::Plugin("Blank.esp");
|
||||
EXPECT_FALSE(plugin.IsActive(game));
|
||||
plugin = loot::Plugin(game, "Blank.esp", true);
|
||||
EXPECT_FALSE(plugin.IsActive());
|
||||
}
|
||||
|
||||
TEST_F(Plugin, EqualityOperator) {
|
||||
|
||||
Reference in New Issue
Block a user