diff --git a/cpp/include/loot/game_interface.h b/cpp/include/loot/game_interface.h index ec64c5bd..ce2e7059 100644 --- a/cpp/include/loot/game_interface.h +++ b/cpp/include/loot/game_interface.h @@ -106,8 +106,8 @@ public: * @brief Parses plugins and loads their data. * @details If a given plugin filename (or one that is case-insensitively * equal) has already been loaded, its previously-loaded data - * data is discarded, invalidating any existing shared pointers to - * that plugin's PluginInterface object. + * data is discarded. Any existing PluginInterface objects are + * unaffected. * * If the game is Morrowind, OpenMW or Starfield, it's only valid to * fully load a plugin if its masters are already loaded or included @@ -126,8 +126,7 @@ public: /** * @brief Clears the plugins loaded by previous calls to `LoadPlugins()`. - * @details This invalidates any PluginInterface pointers retrieved using - * `GetPlugin()` or `GetLoadedPlugins()`. + * @details This does not affect any existing PluginInterface objects. */ virtual void ClearLoadedPlugins() = 0; @@ -136,10 +135,7 @@ public: * @param pluginName * The filename of the plugin to get data for. * @returns A shared pointer to a const PluginInterface implementation. The - * pointer is null if the given plugin has not been loaded. The - * pointer remains valid until the `ClearLoadedPlugins()` function - * is called, this GameInterface is destroyed, or until a plugin with - * a case-insensitively equal filename is loaded. + * pointer is null if the given plugin has not been loaded. */ virtual std::shared_ptr GetPlugin( std::string_view pluginName) const = 0; @@ -147,10 +143,7 @@ public: /** * @brief Get a set of const references to all loaded plugins' PluginInterface * objects. - * @returns A set of shared pointers to const PluginInterface. The pointers - * remain valid until the `ClearLoadedPlugins()` function is called, - * this GameInterface is destroyed, or until a plugin with a - * case-insensitively equal filename is loaded. + * @returns A set of shared pointers to const PluginInterface objects. */ virtual std::vector> GetLoadedPlugins() const = 0; diff --git a/cpp/src/tests/api/interface/game_interface_test.h b/cpp/src/tests/api/interface/game_interface_test.h index 576cfe53..965dda2a 100644 --- a/cpp/src/tests/api/interface/game_interface_test.h +++ b/cpp/src/tests/api/interface/game_interface_test.h @@ -336,6 +336,17 @@ TEST_P(GameInterfaceTest, EXPECT_NE(pointer, newPointer); } +TEST_P(GameInterfaceTest, loadPluginsShouldNotAffectExistingPluginPointers) { + handle_->LoadPlugins({std::filesystem::u8path(blankEsm)}, true); + const auto pointer = handle_->GetPlugin(blankEsm); + ASSERT_NE(nullptr, pointer); + + handle_->LoadPlugins({std::filesystem::u8path(blankEsp)}, true); + + const auto newPointer = handle_->GetPlugin(blankEsm); + EXPECT_EQ(pointer, newPointer); +} + TEST_P(GameInterfaceTest, loadPluginsShouldThrowIfGivenVectorElementsWithTheSameFilename) { const auto dataPluginPath = dataPath / std::filesystem::u8path(blankEsm); @@ -522,10 +533,30 @@ TEST_P(GameInterfaceTest, getPluginThatIsNotCachedShouldReturnANullPointer) { } TEST_P(GameInterfaceTest, - gettingPluginsShouldReturnAnEmptySetIfNoneHaveBeenLoaded) { + getPluginReturnsTheSamePointerForConsecutiveCallsGivenTheSamePlugin) { + handle_->LoadPlugins({std::filesystem::u8path(blankEsm)}, true); + + const auto pointer1 = handle_->GetPlugin(blankEsm); + const auto pointer2 = handle_->GetPlugin(blankEsm); + + EXPECT_EQ(pointer1, pointer2); +} + +TEST_P(GameInterfaceTest, + getLoadedPluginsShouldReturnAnEmptySetIfNoneHaveBeenLoaded) { EXPECT_TRUE(handle_->GetLoadedPlugins().empty()); } +TEST_P(GameInterfaceTest, + getLoadedPluginReturnsTheSamePointersForConsecutiveCalls) { + handle_->LoadPlugins({std::filesystem::u8path(blankEsm)}, true); + + const auto pointers1 = handle_->GetLoadedPlugins(); + const auto pointers2 = handle_->GetLoadedPlugins(); + + EXPECT_EQ(pointers1, pointers2); +} + TEST_P(GameInterfaceTest, sortPluginsShouldSucceedIfPassedValidArguments) { std::vector expectedOrder; if (GetParam() == GameType::starfield) {