mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Cache plugins only after resolving record IDs
This means that if there's an issue while doing that you won't be left with half-loaded plugins.
This commit is contained in:
+10
-4
@@ -264,6 +264,7 @@ void Game::LoadPlugins(const std::vector<std::filesystem::path>& pluginPaths,
|
||||
}
|
||||
|
||||
std::mutex mutex;
|
||||
std::vector<Plugin> plugins;
|
||||
std::for_each(
|
||||
std::execution::par_unseq,
|
||||
pluginPaths.begin(),
|
||||
@@ -273,10 +274,12 @@ void Game::LoadPlugins(const std::vector<std::filesystem::path>& pluginPaths,
|
||||
const auto resolvedPluginPath =
|
||||
ResolvePluginPath(GetType(), DataPath(), pluginPath);
|
||||
|
||||
auto plugin =
|
||||
Plugin(GetType(), cache_, resolvedPluginPath, loadHeadersOnly);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
cache_.AddPlugin(
|
||||
Plugin(GetType(), cache_, resolvedPluginPath, loadHeadersOnly));
|
||||
plugins.push_back(std::move(plugin));
|
||||
} catch (const std::exception& e) {
|
||||
if (logger) {
|
||||
logger->error(
|
||||
@@ -290,13 +293,16 @@ void Game::LoadPlugins(const std::vector<std::filesystem::path>& pluginPaths,
|
||||
if (!loadHeadersOnly &&
|
||||
(GetType() == GameType::tes3 || GetType() == GameType::openmw ||
|
||||
GetType() == GameType::starfield)) {
|
||||
auto plugins = cache_.GetPlugins();
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(plugins);
|
||||
for (auto& plugin : plugins) {
|
||||
plugin->ResolveRecordIds(pluginsMetadata.get());
|
||||
plugin.ResolveRecordIds(pluginsMetadata.get());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& plugin : plugins) {
|
||||
cache_.AddPlugin(std::move(plugin));
|
||||
}
|
||||
|
||||
conditionEvaluator_->RefreshLoadedPluginsState(GetLoadedPlugins());
|
||||
}
|
||||
|
||||
|
||||
+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<const Plugin*>& plugins) {
|
||||
Plugin::GetPluginsMetadata(const std::vector<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<const 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<const Plugin*>& plugins);
|
||||
GetPluginsMetadata(const std::vector<Plugin>& plugins);
|
||||
|
||||
private:
|
||||
void Load(const std::filesystem::path& path,
|
||||
|
||||
@@ -286,19 +286,21 @@ TEST_P(PluginTest, loadingWholePluginShouldReadFields) {
|
||||
game_.GetType(), game_.GetCache(), game_.DataPath() / pluginName, false);
|
||||
|
||||
if (GetParam() == GameType::tes3 || GetParam() == GameType::openmw) {
|
||||
Plugin master(
|
||||
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false);
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata({&master});
|
||||
std::vector<Plugin> masters;
|
||||
masters.push_back(Plugin(
|
||||
game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsm, false));
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(masters);
|
||||
|
||||
EXPECT_NO_THROW(plugin.ResolveRecordIds(pluginsMetadata.get()));
|
||||
|
||||
EXPECT_EQ(4, plugin.GetOverrideRecordCount());
|
||||
} else if (GetParam() == GameType::starfield) {
|
||||
Plugin master(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / blankFullEsm,
|
||||
true);
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata({&master});
|
||||
std::vector<Plugin> masters;
|
||||
masters.push_back(Plugin(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / blankFullEsm,
|
||||
true));
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(masters);
|
||||
|
||||
EXPECT_NO_THROW(plugin.ResolveRecordIds(pluginsMetadata.get()));
|
||||
|
||||
@@ -629,25 +631,27 @@ TEST_P(
|
||||
? blankMasterDependentEsp
|
||||
: blankDifferentPluginDependentEsp;
|
||||
|
||||
Plugin plugin1(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / sourcePluginName,
|
||||
false);
|
||||
Plugin plugin2(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / updatePluginName,
|
||||
false);
|
||||
std::vector<Plugin> plugins;
|
||||
plugins.push_back(Plugin(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / sourcePluginName,
|
||||
false));
|
||||
plugins.push_back(Plugin(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / updatePluginName,
|
||||
false));
|
||||
|
||||
if (GetParam() == GameType::starfield) {
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata({&plugin1});
|
||||
plugin2.ResolveRecordIds(pluginsMetadata.get());
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(plugins);
|
||||
plugins[1].ResolveRecordIds(pluginsMetadata.get());
|
||||
|
||||
plugin1.ResolveRecordIds(nullptr);
|
||||
plugin2.ResolveRecordIds(nullptr);
|
||||
plugins[0].ResolveRecordIds(nullptr);
|
||||
plugins[1].ResolveRecordIds(nullptr);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(plugin1.IsValidAsUpdatePlugin());
|
||||
EXPECT_EQ(GetParam() == GameType::starfield, plugin2.IsValidAsUpdatePlugin());
|
||||
EXPECT_FALSE(plugins[0].IsValidAsUpdatePlugin());
|
||||
EXPECT_EQ(GetParam() == GameType::starfield,
|
||||
plugins[1].IsValidAsUpdatePlugin());
|
||||
}
|
||||
|
||||
TEST_P(PluginTest,
|
||||
@@ -699,20 +703,25 @@ TEST_P(PluginTest,
|
||||
? blankMasterDependentEsm
|
||||
: blankMasterDependentEsm + ".ghost";
|
||||
|
||||
Plugin plugin1(
|
||||
game_.GetType(), game_.GetCache(), game_.DataPath() / plugin1Name, false);
|
||||
Plugin plugin2(
|
||||
game_.GetType(), game_.GetCache(), game_.DataPath() / plugin2Name, false);
|
||||
std::vector<Plugin> plugins;
|
||||
plugins.push_back(Plugin(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / plugin1Name,
|
||||
false));
|
||||
plugins.push_back(Plugin(game_.GetType(),
|
||||
game_.GetCache(),
|
||||
game_.DataPath() / plugin2Name,
|
||||
false));
|
||||
|
||||
if (GetParam() == GameType::starfield) {
|
||||
plugin1.ResolveRecordIds(nullptr);
|
||||
plugins[0].ResolveRecordIds(nullptr);
|
||||
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata({&plugin1});
|
||||
plugin2.ResolveRecordIds(pluginsMetadata.get());
|
||||
const auto pluginsMetadata = Plugin::GetPluginsMetadata(plugins);
|
||||
plugins[1].ResolveRecordIds(pluginsMetadata.get());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(plugin1.DoRecordsOverlap(plugin2));
|
||||
EXPECT_TRUE(plugin2.DoRecordsOverlap(plugin1));
|
||||
EXPECT_TRUE(plugins[0].DoRecordsOverlap(plugins[1]));
|
||||
EXPECT_TRUE(plugins[1].DoRecordsOverlap(plugins[0]));
|
||||
}
|
||||
|
||||
TEST_P(PluginTest,
|
||||
|
||||
Reference in New Issue
Block a user