diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp index e7bf070c8b3..f9e9e83fa7c 100644 --- a/src/io/iologindata.cpp +++ b/src/io/iologindata.cpp @@ -169,19 +169,11 @@ bool IOLoginData::loadPlayer(const std::shared_ptr &player, const DBResu // Load instant spells list IOLoginDataLoad::loadPlayerInstantSpellList(player, result); - if (disableIrrelevantInfo) { - return true; + if (!disableIrrelevantInfo) { + // Load additional data only if the player is online (e.g., forge, bosstiary) + loadOnlyDataForOnlinePlayer(player, result); } - // load forge history - IOLoginDataLoad::loadPlayerForgeHistory(player, result); - - // load bosstiary - IOLoginDataLoad::loadPlayerBosstiary(player, result); - - IOLoginDataLoad::loadPlayerInitializeSystem(player); - IOLoginDataLoad::loadPlayerUpdateSystem(player); - return true; } catch (const std::system_error &error) { g_logger().warn("[{}] Error while load player: {}", __FUNCTION__, error.what()); @@ -192,6 +184,13 @@ bool IOLoginData::loadPlayer(const std::shared_ptr &player, const DBResu } } +void IOLoginData::loadOnlyDataForOnlinePlayer(const std::shared_ptr &player, const DBResult_ptr &result) { + IOLoginDataLoad::loadPlayerForgeHistory(player, result); + IOLoginDataLoad::loadPlayerBosstiary(player, result); + IOLoginDataLoad::loadPlayerInitializeSystem(player); + IOLoginDataLoad::loadPlayerUpdateSystem(player); +} + bool IOLoginData::savePlayer(const std::shared_ptr &player) { try { bool success = DBTransaction::executeWithinTransaction([player]() { @@ -259,6 +258,18 @@ bool IOLoginData::savePlayerGuard(const std::shared_ptr &player) { throw DatabaseException("[IOLoginDataSave::savePlayerTaskHuntingClass] - Failed to save player task hunting class: " + player->getName()); } + // Saves data components that are only valid if the player is online. + // Skips execution entirely if the player is offline to avoid overwriting unloaded data. + saveOnlyDataForOnlinePlayer(player); + + return true; +} + +void IOLoginData::saveOnlyDataForOnlinePlayer(const std::shared_ptr &player) { + if (player->isOffline()) { + return; + } + if (!IOLoginDataSave::savePlayerForgeHistory(player)) { throw DatabaseException("[IOLoginDataSave::savePlayerForgeHistory] - Failed to save player forge history: " + player->getName()); } @@ -279,8 +290,6 @@ bool IOLoginData::savePlayerGuard(const std::shared_ptr &player) { if (!IOLoginDataSave::savePlayerStorage(player)) { throw DatabaseException("[IOLoginDataSave::savePlayerStorage] - Failed to save player storage: " + player->getName()); } - - return true; } std::string IOLoginData::getNameByGuid(uint32_t guid) { diff --git a/src/io/iologindata.hpp b/src/io/iologindata.hpp index 378e1bd2388..3bd5a436555 100644 --- a/src/io/iologindata.hpp +++ b/src/io/iologindata.hpp @@ -25,7 +25,39 @@ class IOLoginData { static bool loadPlayerById(const std::shared_ptr &player, uint32_t id, bool disableIrrelevantInfo = true); static bool loadPlayerByName(const std::shared_ptr &player, const std::string &name, bool disableIrrelevantInfo = true); static bool loadPlayer(const std::shared_ptr &player, const std::shared_ptr &result, bool disableIrrelevantInfo = false); + + /** + * @brief Loads data components that are only relevant when the player is online. + * + * This function is responsible for initializing systems that are not needed when the player is offline, + * such as the forge history, bosstiary, and various runtime systems. + * + * If the player is offline, this function returns early and avoids loading these systems. + * This helps optimize memory usage and prevents unnecessary initialization of unused features. + * + * @param player A shared pointer to the Player instance. Must not be nullptr. + * @param result The database result containing the player's data. + */ + static void loadOnlyDataForOnlinePlayer(const std::shared_ptr &player, const std::shared_ptr &result); + static bool savePlayer(const std::shared_ptr &player); + + /** + * @brief Saves data components that are only relevant when the player is online. + * + * This function is responsible for persisting player-related systems that are only loaded + * when the player is online, such as the forge history, bosstiary progress, and wheel data. + * + * If the player is offline, this function will return immediately without performing any save operations. + * This prevents overwriting existing database values with empty or uninitialized data that may result + * from partial player loading (common during offline operations). + * + * @note This function throws DatabaseException if any of the internal save operations fail. + * It should be called after all always-loaded data has been saved. + * + * @param player A shared pointer to the Player instance. Must not be nullptr. + */ + static void saveOnlyDataForOnlinePlayer(const std::shared_ptr &player); static uint32_t getGuidByName(const std::string &name); static bool getGuidByNameEx(uint32_t &guid, bool &specialVip, std::string &name); static std::string getNameByGuid(uint32_t guid);