From 8e1a0870b7c366bf49be78d57c01ae234fba2968 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Fri, 28 Jun 2024 19:15:09 +0100 Subject: [PATCH] Update esplugin to v6.0.0 --- CMakeLists.txt | 4 +- src/api/game/game.cpp | 9 ++++ src/api/plugin.cpp | 63 +++++++++++++++++++++------ src/api/plugin.h | 8 +++- src/tests/api/internals/plugin_test.h | 52 +++++++++++++++++++++- 5 files changed, 119 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 359921ec..3a614ab4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,8 +73,8 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") endif() if(NOT DEFINED ESPLUGIN_URL) - set(ESPLUGIN_URL "https://github.com/Ortham/esplugin/archive/5.0.1.tar.gz") - set(ESPLUGIN_HASH "SHA256=4feb855e1f90046357497b5f0fdebe3e126f84d8dc9bc468e153bcbcb1aa9171") + set(ESPLUGIN_URL "https://github.com/Ortham/esplugin/archive/refs/tags/6.0.0.tar.gz") + set(ESPLUGIN_HASH "SHA256=d9deea7581bcd823bcc2ce6903a7c711404b6b80242c47d93f70ec79b9ab59b7") endif() ExternalProject_Add(esplugin diff --git a/src/api/game/game.cpp b/src/api/game/game.cpp index d27bb537..e4da8675 100644 --- a/src/api/game/game.cpp +++ b/src/api/game/game.cpp @@ -307,6 +307,15 @@ void Game::LoadPlugins(const std::vector& pluginPaths, } }); + if (!loadHeadersOnly && + (GetType() == GameType::tes3 || GetType() == GameType::starfield)) { + auto plugins = cache_.GetPlugins(); + const auto pluginsMetadata = Plugin::GetPluginsMetadata(plugins); + for (auto& plugin : plugins) { + plugin->ResolveRecordIds(pluginsMetadata.get()); + } + } + conditionEvaluator_->RefreshLoadedPluginsState(GetLoadedPlugins()); } diff --git a/src/api/plugin.cpp b/src/api/plugin.cpp index 488b8a66..726ea178 100644 --- a/src/api/plugin.cpp +++ b/src/api/plugin.cpp @@ -187,8 +187,7 @@ Plugin::Plugin(const GameType gameType, esPlugin( std::unique_ptr<::Plugin, decltype(&esp_plugin_free)>(nullptr, esp_plugin_free)), - isEmpty_(true), - overrideRecordCount_(0) { + isEmpty_(true) { auto logger = getLogger(); try { @@ -206,14 +205,6 @@ Plugin::Plugin(const GameType gameType, if (!headerOnly) { crc_ = GetCrc32(pluginPath); - ret = esp_plugin_count_override_records(esPlugin.get(), - &overrideRecordCount_); - if (ret != ESP_OK) { - throw FileAccessError( - "Error counting override records in \"" + pluginPath.u8string() + - "\". esplugin error code: " + std::to_string(ret)); - } - // Get the assets in the BSAs that this plugin loads. auto assets = GetAssetsInBethesdaArchives(archivePaths_); std::swap(archiveAssets_, assets); @@ -238,6 +229,14 @@ Plugin::Plugin(const GameType gameType, } } +void Plugin::ResolveRecordIds(Vec_PluginMetadata* pluginsMetadata) const { + auto ret = esp_plugin_resolve_record_ids(esPlugin.get(), pluginsMetadata); + if (ret != ESP_OK) { + throw FileAccessError(name_ + + " : esplugin error code: " + std::to_string(ret)); + } +} + std::string Plugin::GetName() const { return name_; } std::optional Plugin::GetHeaderVersion() const { @@ -305,7 +304,7 @@ bool Plugin::IsLightPlugin() const { bool Plugin::IsOverridePlugin() const { bool isOverridePlugin = false; const auto ret = - esp_plugin_is_override_plugin(esPlugin.get(), &isOverridePlugin); + esp_plugin_is_update_plugin(esPlugin.get(), &isOverridePlugin); if (ret != ESP_OK) { throw FileAccessError(name_ + " : esplugin error code: " + std::to_string(ret)); @@ -329,7 +328,7 @@ bool Plugin::IsValidAsLightPlugin() const { bool Plugin::IsValidAsOverridePlugin() const { bool isValid = false; const auto ret = - esp_plugin_is_valid_as_override_plugin(esPlugin.get(), &isValid); + esp_plugin_is_valid_as_update_plugin(esPlugin.get(), &isValid); if (ret != ESP_OK) { throw FileAccessError(name_ + " : esplugin error code: " + std::to_string(ret)); @@ -403,7 +402,17 @@ size_t Plugin::GetOverlapSize( return overlapSize; } -size_t Plugin::GetOverrideRecordCount() const { return overrideRecordCount_; } +size_t Plugin::GetOverrideRecordCount() const { + size_t overrideRecordCount; + const auto ret = + esp_plugin_count_override_records(esPlugin.get(), &overrideRecordCount); + if (ret != ESP_OK) { + throw FileAccessError(name_ + + " : esplugin error code: " + std::to_string(ret)); + } + + return overrideRecordCount; +} uint32_t Plugin::GetRecordAndGroupCount() const { uint32_t recordAndGroupCount = 0; @@ -510,6 +519,34 @@ std::string Plugin::GetDescription() const { return descriptionStr; } +std::unique_ptr +Plugin::GetPluginsMetadata(std::vector plugins) { + if (plugins.empty()) { + return std::unique_ptr( + nullptr, esp_plugins_metadata_free); + } + + std::vector esPlugins; + esPlugins.reserve(plugins.size()); + for (const auto& plugin : plugins) { + esPlugins.push_back(plugin->esPlugin.get()); + } + + Vec_PluginMetadata* pluginsMetadata = nullptr; + const auto ret = esp_get_plugins_metadata( + esPlugins.data(), esPlugins.size(), &pluginsMetadata); + if (ret != ESP_OK) { + throw FileAccessError( + "Failed to get plugins metadata: esplugin error code: " + + std::to_string(ret)); + } + + return std::unique_ptr( + pluginsMetadata, esp_plugins_metadata_free); +} + std::string GetArchiveFileExtension(const GameType gameType) { if (gameType == GameType::fo4 || gameType == GameType::fo4vr || gameType == GameType::starfield) diff --git a/src/api/plugin.h b/src/api/plugin.h index e56cb0ca..1295049e 100644 --- a/src/api/plugin.h +++ b/src/api/plugin.h @@ -60,6 +60,8 @@ public: std::filesystem::path pluginPath, const bool headerOnly); + void ResolveRecordIds(Vec_PluginMetadata* pluginsMetadata) const; + std::string GetName() const override; std::optional GetHeaderVersion() const override; std::optional GetVersion() const override; @@ -91,6 +93,11 @@ public: static bool IsValid(const GameType gameType, const std::filesystem::path& pluginPath); + static std::unique_ptr + GetPluginsMetadata( + std::vector); + private: void Load(const std::filesystem::path& path, GameType gameType, @@ -103,7 +110,6 @@ private: std::unique_ptr<::Plugin, decltype(&esp_plugin_free)> esPlugin; bool isEmpty_; // Does the plugin contain any records other than the TES4 // header? - size_t overrideRecordCount_; std::optional version_; // Obtained from description field. std::optional crc_; std::vector tags_; diff --git a/src/tests/api/internals/plugin_test.h b/src/tests/api/internals/plugin_test.h index 3c4817b5..2b2aeffe 100644 --- a/src/tests/api/internals/plugin_test.h +++ b/src/tests/api/internals/plugin_test.h @@ -299,8 +299,22 @@ TEST_P(PluginTest, loadingWholePluginShouldReadFields) { false); if (GetParam() == GameType::tes3) { - EXPECT_EQ(0, plugin.GetOverrideRecordCount()); + 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) { + Plugin master(game_.GetType(), + game_.GetCache(), + game_.DataPath() / blankFullEsm, + true); + const auto pluginsMetadata = Plugin::GetPluginsMetadata({&master}); + + EXPECT_NO_THROW(plugin.ResolveRecordIds(pluginsMetadata.get())); + EXPECT_EQ(1, plugin.GetOverrideRecordCount()); } else { EXPECT_EQ(4, plugin.GetOverrideRecordCount()); @@ -548,6 +562,14 @@ TEST_P( game_.DataPath() / overridePluginName, false); + if (GetParam() == GameType::starfield) { + const auto pluginsMetadata = Plugin::GetPluginsMetadata({&plugin1}); + plugin2.ResolveRecordIds(pluginsMetadata.get()); + + plugin1.ResolveRecordIds(nullptr); + plugin2.ResolveRecordIds(nullptr); + } + EXPECT_FALSE(plugin1.IsValidAsOverridePlugin()); EXPECT_EQ(GetParam() == GameType::starfield, plugin2.IsValidAsOverridePlugin()); @@ -583,6 +605,11 @@ TEST_P(PluginTest, Plugin plugin2( game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsp, false); + if (GetParam() == GameType::starfield) { + plugin1.ResolveRecordIds(nullptr); + plugin2.ResolveRecordIds(nullptr); + } + EXPECT_FALSE(plugin1.DoRecordsOverlap(plugin2)); EXPECT_FALSE(plugin2.DoRecordsOverlap(plugin1)); } @@ -599,6 +626,13 @@ TEST_P(PluginTest, game_.DataPath() / (blankMasterDependentEsm + ".ghost"), false); + if (GetParam() == GameType::starfield) { + plugin1.ResolveRecordIds(nullptr); + + const auto pluginsMetadata = Plugin::GetPluginsMetadata({&plugin1}); + plugin2.ResolveRecordIds(pluginsMetadata.get()); + } + EXPECT_TRUE(plugin1.DoRecordsOverlap(plugin2)); EXPECT_TRUE(plugin2.DoRecordsOverlap(plugin1)); } @@ -626,6 +660,11 @@ TEST_P(PluginTest, getOverlapSizeShouldCountEachRecordOnce) { false); if (GetParam() == GameType::starfield) { + plugin1.ResolveRecordIds(nullptr); + + const auto pluginsMetadata = Plugin::GetPluginsMetadata({&plugin1}); + plugin2.ResolveRecordIds(pluginsMetadata.get()); + EXPECT_EQ(1, plugin1.GetOverlapSize({&plugin2, &plugin2})); } else { EXPECT_EQ(4, plugin1.GetOverlapSize({&plugin2, &plugin2})); @@ -646,6 +685,12 @@ TEST_P(PluginTest, getOverlapSizeShouldCheckAgainstAllGivenPlugins) { false); if (GetParam() == GameType::starfield) { + plugin1.ResolveRecordIds(nullptr); + plugin2.ResolveRecordIds(nullptr); + + const auto pluginsMetadata = Plugin::GetPluginsMetadata({&plugin1}); + plugin3.ResolveRecordIds(pluginsMetadata.get()); + EXPECT_EQ(1, plugin1.GetOverlapSize({&plugin2, &plugin3})); } else { EXPECT_EQ(4, plugin1.GetOverlapSize({&plugin2, &plugin3})); @@ -670,6 +715,11 @@ TEST_P(PluginTest, getOverlapSizeShouldReturnZeroForPluginsThatDoNotOverlap) { Plugin plugin2( game_.GetType(), game_.GetCache(), game_.DataPath() / blankEsp, false); + if (GetParam() == GameType::starfield) { + plugin1.ResolveRecordIds(nullptr); + plugin2.ResolveRecordIds(nullptr); + } + EXPECT_EQ(0, plugin1.GetOverlapSize({&plugin2})); }