mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Fix LoadPlugins() with missing already-loaded plugins
This commit is contained in:
@@ -293,7 +293,9 @@ void Game::LoadPlugins(const std::vector<std::filesystem::path>& pluginPaths,
|
||||
if (!loadHeadersOnly &&
|
||||
(GetType() == GameType::tes3 || GetType() == GameType::openmw ||
|
||||
GetType() == GameType::starfield)) {
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(plugins);
|
||||
const auto loadedPlugins = cache_.GetPluginsWithReplacements(plugins);
|
||||
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(loadedPlugins);
|
||||
for (auto& plugin : plugins) {
|
||||
plugin.ResolveRecordIds(pluginsMetadata.get());
|
||||
}
|
||||
@@ -306,9 +308,7 @@ void Game::LoadPlugins(const std::vector<std::filesystem::path>& pluginPaths,
|
||||
conditionEvaluator_->RefreshLoadedPluginsState(GetLoadedPlugins());
|
||||
}
|
||||
|
||||
void Game::ClearLoadedPlugins() {
|
||||
cache_.ClearCachedPlugins();
|
||||
}
|
||||
void Game::ClearLoadedPlugins() { cache_.ClearCachedPlugins(); }
|
||||
|
||||
const PluginInterface* Game::GetPlugin(const std::string& pluginName) const {
|
||||
return cache_.GetPlugin(pluginName);
|
||||
@@ -348,9 +348,9 @@ std::vector<std::string> Game::SortPlugins(
|
||||
|
||||
const auto newLoadOrder =
|
||||
loot::SortPlugins(std::move(pluginsSortingData),
|
||||
database_.GetGroups(false),
|
||||
database_.GetUserGroups(),
|
||||
loadOrderHandler_.GetEarlyLoadingPlugins());
|
||||
database_.GetGroups(false),
|
||||
database_.GetUserGroups(),
|
||||
loadOrderHandler_.GetEarlyLoadingPlugins());
|
||||
|
||||
if (logger) {
|
||||
logger->debug("Calculated order:");
|
||||
|
||||
@@ -56,6 +56,24 @@ void GameCache::AddPlugin(Plugin&& plugin) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const Plugin*> GameCache::GetPluginsWithReplacements(
|
||||
const std::vector<Plugin>& newPlugins) const {
|
||||
std::unordered_map<std::string, const Plugin*> pluginsMap;
|
||||
for (const auto& plugin : newPlugins) {
|
||||
pluginsMap.emplace(NormalizeFilename(plugin.GetName()), &plugin);
|
||||
}
|
||||
for (const auto& [key, plugin] : plugins_) {
|
||||
pluginsMap.emplace(key, plugin.get());
|
||||
}
|
||||
|
||||
std::vector<const Plugin*> loadedPlugins;
|
||||
for (const auto& [key, plugin] : pluginsMap) {
|
||||
loadedPlugins.push_back(plugin);
|
||||
}
|
||||
|
||||
return loadedPlugins;
|
||||
}
|
||||
|
||||
std::set<std::filesystem::path> GameCache::GetArchivePaths() const {
|
||||
return archivePaths_;
|
||||
}
|
||||
@@ -64,7 +82,5 @@ void GameCache::CacheArchivePaths(std::set<std::filesystem::path>&& paths) {
|
||||
archivePaths_ = std::move(paths);
|
||||
}
|
||||
|
||||
void GameCache::ClearCachedPlugins() {
|
||||
plugins_.clear();
|
||||
}
|
||||
void GameCache::ClearCachedPlugins() { plugins_.clear(); }
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@ public:
|
||||
const Plugin* GetPlugin(const std::string& pluginName) const;
|
||||
void AddPlugin(Plugin&& plugin);
|
||||
|
||||
std::vector<const Plugin*> GetPluginsWithReplacements(
|
||||
const std::vector<Plugin>& newPlugins) const;
|
||||
|
||||
std::set<std::filesystem::path> GetArchivePaths() const;
|
||||
void CacheArchivePaths(std::set<std::filesystem::path>&& paths);
|
||||
|
||||
|
||||
+3
-3
@@ -593,7 +593,7 @@ std::string Plugin::GetDescription() const {
|
||||
}
|
||||
|
||||
std::unique_ptr<Vec_PluginMetadata, decltype(&esp_plugins_metadata_free)>
|
||||
Plugin::GetPluginsMetadata(const std::vector<Plugin>& plugins) {
|
||||
Plugin::GetPluginsMetadata(const std::vector<const Plugin*>& plugins) {
|
||||
if (plugins.empty()) {
|
||||
return std::unique_ptr<Vec_PluginMetadata,
|
||||
decltype(&esp_plugins_metadata_free)>(
|
||||
@@ -603,9 +603,9 @@ Plugin::GetPluginsMetadata(const std::vector<Plugin>& plugins) {
|
||||
std::vector<const ::Plugin*> esPlugins;
|
||||
esPlugins.reserve(plugins.size());
|
||||
for (const auto& plugin : plugins) {
|
||||
const auto esPlugin = plugin.esPlugin.get();
|
||||
const auto esPlugin = plugin->esPlugin.get();
|
||||
if (esPlugin != nullptr) {
|
||||
esPlugins.push_back(plugin.esPlugin.get());
|
||||
esPlugins.push_back(plugin->esPlugin.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ public:
|
||||
|
||||
static std::unique_ptr<Vec_PluginMetadata,
|
||||
decltype(&esp_plugins_metadata_free)>
|
||||
GetPluginsMetadata(const std::vector<Plugin>& plugins);
|
||||
GetPluginsMetadata(const std::vector<const Plugin*>& plugins);
|
||||
|
||||
private:
|
||||
void Load(const std::filesystem::path& path,
|
||||
|
||||
@@ -445,6 +445,42 @@ TEST_P(
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(
|
||||
GameTest,
|
||||
loadPluginsShouldThrowIfAPluginHasAMasterThatIsNotInTheInputAndIsNotAlreadyLoadedAndGameIsMorrowindOrStarfield) {
|
||||
Game game = Game(GetParam(), gamePath, localPath);
|
||||
|
||||
if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw ||
|
||||
GetParam() == GameType::starfield) {
|
||||
try {
|
||||
game.LoadPlugins({blankMasterDependentEsm}, false);
|
||||
FAIL();
|
||||
} catch (const std::system_error& e) {
|
||||
EXPECT_EQ(ESP_ERROR_PLUGIN_METADATA_NOT_FOUND, e.code().value());
|
||||
EXPECT_EQ(esplugin_category(), e.code().category());
|
||||
}
|
||||
} else {
|
||||
game.LoadPlugins({blankMasterDependentEsm}, false);
|
||||
|
||||
EXPECT_NE(nullptr, game.GetPlugin(blankMasterDependentEsm));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(
|
||||
GameTest,
|
||||
loadPluginsShouldNotThrowIfAPluginHasAMasterThatIsNotInTheInputButIsAlreadyLoaded) {
|
||||
Game game = Game(GetParam(), gamePath, localPath);
|
||||
|
||||
const auto pluginName =
|
||||
GetParam() == GameType::starfield ? blankFullEsm : blankEsm;
|
||||
|
||||
game.LoadPlugins({pluginName}, true);
|
||||
|
||||
game.LoadPlugins({blankMasterDependentEsm}, false);
|
||||
|
||||
EXPECT_NE(nullptr, game.GetPlugin(blankMasterDependentEsm));
|
||||
}
|
||||
|
||||
TEST_P(GameTest, sortPluginsWithNoLoadedPluginsShouldReturnAnEmptyList) {
|
||||
Game game = Game(GetParam(), gamePath, localPath);
|
||||
|
||||
|
||||
@@ -353,21 +353,19 @@ TEST_P(PluginTest, loadingWholePluginShouldReadFields) {
|
||||
game_.GetType(), game_.GetCache(), game_.DataPath() / pluginName, false);
|
||||
|
||||
if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw) {
|
||||
std::vector<Plugin> masters;
|
||||
masters.push_back(Plugin(
|
||||
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false));
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(masters);
|
||||
Plugin master(
|
||||
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false);
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata({&master});
|
||||
|
||||
EXPECT_NO_THROW(plugin.ResolveRecordIds(pluginsMetadata.get()));
|
||||
|
||||
EXPECT_EQ(4, plugin.GetOverrideRecordCount());
|
||||
} else if (GetParam() == GameType::starfield) {
|
||||
std::vector<Plugin> masters;
|
||||
masters.push_back(Plugin(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / blankFullEsm,
|
||||
true));
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(masters);
|
||||
Plugin master(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / blankFullEsm,
|
||||
true);
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata({&master});
|
||||
|
||||
EXPECT_NO_THROW(plugin.ResolveRecordIds(pluginsMetadata.get()));
|
||||
|
||||
@@ -709,7 +707,8 @@ TEST_P(
|
||||
false));
|
||||
|
||||
if (GetParam() == GameType::starfield) {
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(plugins);
|
||||
const auto pluginsMetadata =
|
||||
Plugin::GetPluginsMetadata({&plugins[0], &plugins[1]});
|
||||
plugins[1].ResolveRecordIds(pluginsMetadata.get());
|
||||
|
||||
plugins[0].ResolveRecordIds(nullptr);
|
||||
@@ -782,7 +781,8 @@ TEST_P(PluginTest,
|
||||
if (GetParam() == GameType::starfield) {
|
||||
plugins[0].ResolveRecordIds(nullptr);
|
||||
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(plugins);
|
||||
const auto pluginsMetadata =
|
||||
Plugin::GetPluginsMetadata({&plugins[0], &plugins[1]});
|
||||
plugins[1].ResolveRecordIds(pluginsMetadata.get());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user