Skip to content

Commit

Permalink
fix: player lose items with wrong loading offline informations (#2919)
Browse files Browse the repository at this point in the history
When the player is offline, in some scenarios the empty items would load
and the items would be overlapped with the empty table of the offline
player.

Resolves #2917

Related to: #2910
  • Loading branch information
dudantas committed Oct 9, 2024
1 parent 594fe89 commit 72016b2
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/creatures/players/cyclopedia/player_badge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ bool PlayerBadge::loyalty(uint8_t amount) {
}

bool PlayerBadge::accountAllLevel(uint8_t amount) {
const auto &players = g_game().getPlayersByAccount(m_player.getAccount(), true);
auto players = g_game().getPlayersByAccount(m_player.getAccount(), true);
uint16_t total = std::accumulate(players.begin(), players.end(), 0, [](uint16_t sum, const std::shared_ptr<Player> &player) {
return sum + player->getLevel();
});
Expand Down
10 changes: 7 additions & 3 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1012,8 +1012,9 @@ std::shared_ptr<Player> Game::getPlayerByGUID(const uint32_t &guid, bool allowOf
if (!allowOffline) {
return nullptr;
}

std::shared_ptr<Player> tmpPlayer = std::make_shared<Player>(nullptr);
if (!IOLoginData::loadPlayerById(tmpPlayer, guid)) {
if (!IOLoginData::loadPlayerById(tmpPlayer, guid, false)) {
return nullptr;
}
tmpPlayer->setOnline(false);
Expand All @@ -1027,7 +1028,9 @@ std::string Game::getPlayerNameByGUID(const uint32_t &guid) {
if (m_playerNameCache.contains(guid)) {
return m_playerNameCache.at(guid);
}
auto player = getPlayerByGUID(guid, true);

// This player need read-only purposes and never saved
const auto &player = getPlayerByGUID(guid, true);
auto name = player ? player->getName() : "";
if (!name.empty()) {
m_playerNameCache[guid] = name;
Expand Down Expand Up @@ -1066,9 +1069,10 @@ std::vector<std::shared_ptr<Player>> Game::getPlayersByAccount(std::shared_ptr<A
if (error != enumToValue(AccountErrors_t::Ok)) {
return {};
}

std::vector<std::shared_ptr<Player>> ret;
for (const auto &[name, _] : accountPlayers) {
auto player = getPlayerByName(name, allowOffline);
const auto &player = getPlayerByName(name, allowOffline);
if (player) {
ret.push_back(player);
}
Expand Down
63 changes: 33 additions & 30 deletions src/io/functions/iologindata_load_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ bool IOLoginDataLoad::preLoadPlayer(std::shared_ptr<Player> player, const std::s
return true;
}

bool IOLoginDataLoad::loadPlayerFirst(std::shared_ptr<Player> player, DBResult_ptr result) {
bool IOLoginDataLoad::loadPlayerBasicInfo(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return false;
}

Expand Down Expand Up @@ -182,12 +182,15 @@ bool IOLoginDataLoad::loadPlayerFirst(std::shared_ptr<Player> player, DBResult_p
player->setMaxManaShield(result->getNumber<uint32_t>("max_manashield"));

player->setMarriageSpouse(result->getNumber<int32_t>("marriage_spouse"));

// Experience load
IOLoginDataLoad::loadPlayerExperience(player, result);
return true;
}

void IOLoginDataLoad::loadPlayerExperience(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -210,7 +213,7 @@ void IOLoginDataLoad::loadPlayerExperience(std::shared_ptr<Player> player, DBRes

void IOLoginDataLoad::loadPlayerBlessings(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -221,7 +224,7 @@ void IOLoginDataLoad::loadPlayerBlessings(std::shared_ptr<Player> player, DBResu

void IOLoginDataLoad::loadPlayerConditions(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -241,13 +244,13 @@ void IOLoginDataLoad::loadPlayerConditions(std::shared_ptr<Player> player, DBRes

void IOLoginDataLoad::loadPlayerDefaultOutfit(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

player->defaultOutfit.lookType = result->getNumber<uint16_t>("looktype");
if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS, __FUNCTION__) && player->defaultOutfit.lookType != 0 && !g_game().isLookTypeRegistered(player->defaultOutfit.lookType)) {
g_logger().warn("[IOLoginData::loadPlayer] An unregistered creature looktype type with id '{}' was blocked to prevent client crash.", player->defaultOutfit.lookType);
g_logger().warn("[{}] An unregistered creature looktype type with id '{}' was blocked to prevent client crash.", __FUNCTION__, player->defaultOutfit.lookType);
return;
}

Expand All @@ -263,7 +266,7 @@ void IOLoginDataLoad::loadPlayerDefaultOutfit(std::shared_ptr<Player> player, DB
player->defaultOutfit.lookFamiliarsType = result->getNumber<uint16_t>("lookfamiliarstype");

if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS, __FUNCTION__) && player->defaultOutfit.lookFamiliarsType != 0 && !g_game().isLookTypeRegistered(player->defaultOutfit.lookFamiliarsType)) {
g_logger().warn("[IOLoginData::loadPlayer] An unregistered creature looktype type with id '{}' was blocked to prevent client crash.", player->defaultOutfit.lookFamiliarsType);
g_logger().warn("[{}] An unregistered creature looktype type with id '{}' was blocked to prevent client crash.", __FUNCTION__, player->defaultOutfit.lookFamiliarsType);
return;
}

Expand All @@ -272,7 +275,7 @@ void IOLoginDataLoad::loadPlayerDefaultOutfit(std::shared_ptr<Player> player, DB

void IOLoginDataLoad::loadPlayerSkullSystem(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -294,7 +297,7 @@ void IOLoginDataLoad::loadPlayerSkullSystem(std::shared_ptr<Player> player, DBRe

void IOLoginDataLoad::loadPlayerSkill(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -316,7 +319,7 @@ void IOLoginDataLoad::loadPlayerSkill(std::shared_ptr<Player> player, DBResult_p

void IOLoginDataLoad::loadPlayerKills(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -335,7 +338,7 @@ void IOLoginDataLoad::loadPlayerKills(std::shared_ptr<Player> player, DBResult_p

void IOLoginDataLoad::loadPlayerGuild(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -385,7 +388,7 @@ void IOLoginDataLoad::loadPlayerGuild(std::shared_ptr<Player> player, DBResult_p

void IOLoginDataLoad::loadPlayerStashItems(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -401,7 +404,7 @@ void IOLoginDataLoad::loadPlayerStashItems(std::shared_ptr<Player> player, DBRes

void IOLoginDataLoad::loadPlayerBestiaryCharms(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -454,7 +457,7 @@ void IOLoginDataLoad::loadPlayerBestiaryCharms(std::shared_ptr<Player> player, D

void IOLoginDataLoad::loadPlayerInstantSpellList(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player nullptr", __FUNCTION__);
return;
}

Expand All @@ -470,7 +473,7 @@ void IOLoginDataLoad::loadPlayerInstantSpellList(std::shared_ptr<Player> player,

void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -552,7 +555,7 @@ void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr<Player> player, D

void IOLoginDataLoad::loadPlayerStoreInbox(std::shared_ptr<Player> player) {
if (!player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player nullptr", __FUNCTION__);
return;
}

Expand All @@ -563,7 +566,7 @@ void IOLoginDataLoad::loadPlayerStoreInbox(std::shared_ptr<Player> player) {

void IOLoginDataLoad::loadRewardItems(std::shared_ptr<Player> player) {
if (!player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player nullptr", __FUNCTION__);
return;
}

Expand All @@ -581,7 +584,7 @@ void IOLoginDataLoad::loadRewardItems(std::shared_ptr<Player> player) {

void IOLoginDataLoad::loadPlayerDepotItems(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -620,7 +623,7 @@ void IOLoginDataLoad::loadPlayerDepotItems(std::shared_ptr<Player> player, DBRes

void IOLoginDataLoad::loadPlayerInboxItems(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -656,7 +659,7 @@ void IOLoginDataLoad::loadPlayerInboxItems(std::shared_ptr<Player> player, DBRes

void IOLoginDataLoad::loadPlayerStorageMap(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -672,7 +675,7 @@ void IOLoginDataLoad::loadPlayerStorageMap(std::shared_ptr<Player> player, DBRes

void IOLoginDataLoad::loadPlayerVip(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -710,7 +713,7 @@ void IOLoginDataLoad::loadPlayerVip(std::shared_ptr<Player> player, DBResult_ptr

void IOLoginDataLoad::loadPlayerPreyClass(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -757,7 +760,7 @@ void IOLoginDataLoad::loadPlayerPreyClass(std::shared_ptr<Player> player, DBResu

void IOLoginDataLoad::loadPlayerTaskHuntingClass(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -807,7 +810,7 @@ void IOLoginDataLoad::loadPlayerTaskHuntingClass(std::shared_ptr<Player> player,

void IOLoginDataLoad::loadPlayerForgeHistory(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

Expand All @@ -828,12 +831,12 @@ void IOLoginDataLoad::loadPlayerForgeHistory(std::shared_ptr<Player> player, DBR

void IOLoginDataLoad::loadPlayerBosstiary(std::shared_ptr<Player> player, DBResult_ptr result) {
if (!result) {
g_logger().warn("[IOLoginData::loadPlayer] - Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Result nullptr", __FUNCTION__);
return;
}

if (!player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Result nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -865,7 +868,7 @@ void IOLoginDataLoad::loadPlayerBosstiary(std::shared_ptr<Player> player, DBResu

void IOLoginDataLoad::bindRewardBag(std::shared_ptr<Player> player, ItemsMap &rewardItemsMap) {
if (!player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player nullptr", __FUNCTION__);
return;
}

Expand Down Expand Up @@ -905,7 +908,7 @@ void IOLoginDataLoad::insertItemsIntoRewardBag(const ItemsMap &rewardItemsMap) {

void IOLoginDataLoad::loadPlayerInitializeSystem(std::shared_ptr<Player> player) {
if (!player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player nullptr", __FUNCTION__);
return;
}

Expand All @@ -924,7 +927,7 @@ void IOLoginDataLoad::loadPlayerInitializeSystem(std::shared_ptr<Player> player)

void IOLoginDataLoad::loadPlayerUpdateSystem(std::shared_ptr<Player> player) {
if (!player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player nullptr: {}", __FUNCTION__);
g_logger().warn("[{}] - Player nullptr", __FUNCTION__);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/io/functions/iologindata_load_player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

class IOLoginDataLoad : public IOLoginData {
public:
static bool loadPlayerFirst(std::shared_ptr<Player> player, DBResult_ptr result);
static bool loadPlayerBasicInfo(std::shared_ptr<Player> player, DBResult_ptr result);
static bool preLoadPlayer(std::shared_ptr<Player> player, const std::string &name);
static void loadPlayerExperience(std::shared_ptr<Player> player, DBResult_ptr result);
static void loadPlayerBlessings(std::shared_ptr<Player> player, DBResult_ptr result);
Expand Down
20 changes: 8 additions & 12 deletions src/io/iologindata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,22 @@ void IOLoginData::updateOnlineStatus(uint32_t guid, bool login) {
Database::getInstance().executeQuery(query.str());
}

// The boolean "disableIrrelevantInfo" will deactivate the loading of information that is not relevant to the preload, for example, forge, bosstiary, etc. None of this we need to access if the player is offline
bool IOLoginData::loadPlayerById(std::shared_ptr<Player> player, uint32_t id, bool disableIrrelevantInfo /* = true*/) {
// The boolean "loadBasicInfoOnly" will deactivate the loading of information that is not relevant to the preload, for example, forge, bosstiary, etc. None of this we need to access if the player is offline
bool IOLoginData::loadPlayerById(std::shared_ptr<Player> player, uint32_t id, bool loadBasicInfoOnly /* = true*/) {
Database &db = Database::getInstance();
std::ostringstream query;
query << "SELECT * FROM `players` WHERE `id` = " << id;
return loadPlayer(player, db.storeQuery(query.str()), disableIrrelevantInfo);
return loadPlayer(player, db.storeQuery(query.str()), loadBasicInfoOnly);
}

bool IOLoginData::loadPlayerByName(std::shared_ptr<Player> player, const std::string &name, bool disableIrrelevantInfo /* = true*/) {
bool IOLoginData::loadPlayerByName(std::shared_ptr<Player> player, const std::string &name, bool loadBasicInfoOnly /* = true*/) {
Database &db = Database::getInstance();
std::ostringstream query;
query << "SELECT * FROM `players` WHERE `name` = " << db.escapeString(name);
return loadPlayer(player, db.storeQuery(query.str()), disableIrrelevantInfo);
return loadPlayer(player, db.storeQuery(query.str()), loadBasicInfoOnly);
}

bool IOLoginData::loadPlayer(std::shared_ptr<Player> player, DBResult_ptr result, bool disableIrrelevantInfo /* = false*/) {
bool IOLoginData::loadPlayer(std::shared_ptr<Player> player, DBResult_ptr result, bool loadBasicInfoOnly /* = false*/) {
if (!result || !player) {
std::string nullptrType = !result ? "Result" : "Player";
g_logger().warn("[{}] - {} is nullptr", __FUNCTION__, nullptrType);
Expand All @@ -116,12 +116,8 @@ bool IOLoginData::loadPlayer(std::shared_ptr<Player> player, DBResult_ptr result

try {
// First
IOLoginDataLoad::loadPlayerFirst(player, result);

// Experience load
IOLoginDataLoad::loadPlayerExperience(player, result);

if (disableIrrelevantInfo) {
IOLoginDataLoad::loadPlayerBasicInfo(player, result);
if (loadBasicInfoOnly) {
return true;
}

Expand Down
6 changes: 3 additions & 3 deletions src/io/iologindata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class IOLoginData {
static bool gameWorldAuthentication(const std::string &accountDescriptor, const std::string &sessionOrPassword, std::string &characterName, uint32_t &accountId, bool oldProcotol, const uint32_t ip);
static uint8_t getAccountType(uint32_t accountId);
static void updateOnlineStatus(uint32_t guid, bool login);
static bool loadPlayerById(std::shared_ptr<Player> player, uint32_t id, bool disableIrrelevantInfo = true);
static bool loadPlayerByName(std::shared_ptr<Player> player, const std::string &name, bool disableIrrelevantInfo = true);
static bool loadPlayer(std::shared_ptr<Player> player, DBResult_ptr result, bool disableIrrelevantInfo = false);
static bool loadPlayerById(std::shared_ptr<Player> player, uint32_t id, bool loadBasicInfoOnly = true);
static bool loadPlayerByName(std::shared_ptr<Player> player, const std::string &name, bool loadBasicInfoOnly = true);
static bool loadPlayer(std::shared_ptr<Player> player, DBResult_ptr result, bool loadBasicInfoOnly = false);
static bool savePlayer(std::shared_ptr<Player> player);
static uint32_t getGuidByName(const std::string &name);
static bool getGuidByNameEx(uint32_t &guid, bool &specialVip, std::string &name);
Expand Down

0 comments on commit 72016b2

Please sign in to comment.