diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index 6ee605769a7..6101ff0473d 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -813,7 +813,17 @@ bool Creature::dropCorpse(std::shared_ptr lastHitCreature, std::shared player->sendLootMessage(lootMessage.str()); } - if (player->checkAutoLoot(monster->isRewardBoss()) && corpseContainer && mostDamageCreature->getPlayer()) { + stdext::arraylist dirList(128); + FindPathParams fpp; + fpp.minTargetDist = 0; + fpp.maxTargetDist = 1; + fpp.fullPathSearch = true; + fpp.clearSight = true; + fpp.maxSearchDist = 0; + + auto isReachable = g_game().map.getPathMatching(player->getPosition(), dirList, FrozenPathingConditionCall(corpse->getPosition()), fpp); + + if (player->checkAutoLoot(monster->isRewardBoss()) && corpseContainer && mostDamageCreature->getPlayer() && isReachable) { g_dispatcher().addEvent([player, corpseContainer, corpsePosition = corpse->getPosition()] { g_game().playerQuickLootCorpse(player, corpseContainer, corpsePosition); }, diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 76ca1755c70..fd0753c6ac3 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -5158,6 +5158,7 @@ void Player::addUnjustifiedDead(std::shared_ptr attacked) { sendTextMessage(MESSAGE_EVENT_ADVANCE, "Warning! The murder of " + attacked->getName() + " was not justified."); unjustifiedKills.emplace_back(attacked->getGUID(), time(nullptr), true); + setSaveUnjustifiedKills(true); uint8_t dayKills = 0; uint8_t weekKills = 0; @@ -5248,11 +5249,13 @@ double Player::getLostPercent() const { void Player::learnInstantSpell(const std::string &spellName) { if (!hasLearnedInstantSpell(spellName)) { learnedInstantSpellList.push_front(spellName); + setSaveSpells(true); } } void Player::forgetInstantSpell(const std::string &spellName) { learnedInstantSpellList.remove(spellName); + setSaveSpells(true); } bool Player::hasLearnedInstantSpell(const std::string &spellName) const { @@ -6452,7 +6455,7 @@ void Player::stowItem(std::shared_ptr item, uint32_t count, bool allItems) // Stow locker items std::shared_ptr depotLocker = getDepotLocker(getLastDepotId()); auto [itemVector, itemMap] = requestLockerItems(depotLocker); - for (auto lockerItem : itemVector) { + for (const auto &lockerItem : itemVector) { if (lockerItem == nullptr) { break; } @@ -6463,7 +6466,7 @@ void Player::stowItem(std::shared_ptr item, uint32_t count, bool allItems) } } else if (item->getContainer()) { itemDict = item->getContainer()->getStowableItems(); - for (std::shared_ptr containerItem : item->getContainer()->getItems(true)) { + for (const std::shared_ptr &containerItem : item->getContainer()->getItems(true)) { uint32_t depotChest = g_configManager().getNumber(DEPOTCHEST, __FUNCTION__); bool validDepot = depotChest > 0 && depotChest < 21; if (g_configManager().getBoolean(STASH_MOVING, __FUNCTION__) && containerItem && !containerItem->isStackable() && validDepot) { @@ -6473,10 +6476,10 @@ void Player::stowItem(std::shared_ptr item, uint32_t count, bool allItems) } } } else { - itemDict.push_back(std::pair, uint32_t>(item, count)); + itemDict.emplace_back(item, count); } - if (itemDict.size() == 0) { + if (itemDict.empty()) { sendCancelMessage("There is no stowable items on this container."); return; } diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 592db179071..d6d19d287f8 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -689,6 +689,7 @@ class Player final : public Creature, public Cylinder, public Bankable { auto it = stashItems.find(itemId); if (it != stashItems.end()) { stashItems[itemId] += amount; + setSaveStash(true); return; } @@ -711,6 +712,7 @@ class Player final : public Creature, public Cylinder, public Bankable { } else { return false; } + setSaveStash(true); return true; } return false; @@ -2597,6 +2599,25 @@ class Player final : public Creature, public Cylinder, public Bankable { bool canSpeakWithHireling(uint8_t speechbubble); + bool hasSaveStash() { + return saveStash; + } + void setSaveStash(bool onOff) { + saveStash = onOff; + } + bool hasSaveUnjustifiedKills() { + return saveUnjustifiedKills; + } + void setSaveUnjustifiedKills(bool onOff) { + saveUnjustifiedKills = onOff; + } + bool hasSaveSpells() { + return saveSpells; + } + void setSaveSpells(bool onOff) { + saveSpells = onOff; + } + private: friend class PlayerLock; std::mutex mutex; @@ -2819,6 +2840,8 @@ class Player final : public Creature, public Cylinder, public Bankable { uint16_t storeXpBoost = 0; uint16_t staminaXpBoost = 100; int16_t lastDepotId = -1; + + // Stash StashItemList stashItems; // [ItemID] = amount uint32_t movedItems = 0; @@ -2889,6 +2912,11 @@ class Player final : public Creature, public Cylinder, public Bankable { bool dead = false; bool imbuementTrackerWindowOpen = false; + // Otimize Save Players + bool saveStash = false; + bool saveUnjustifiedKills = false; + bool saveSpells = false; + // Hazard system int64_t lastHazardSystemCriticalHit = 0; bool reloadHazardSystemPointsCounter = true; diff --git a/src/game/game.cpp b/src/game/game.cpp index 6754e990595..483b9575ff3 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -419,6 +419,10 @@ void Game::setGameState(GameState_t newState) { } case GAME_STATE_SHUTDOWN: { + g_logger().info("Total save: {}", g_game().getImproveSave(1)); + g_logger().info("Improve Save Stash: {}", g_game().getImproveSave(2)); + g_logger().info("Improve Save Spells: {}", g_game().getImproveSave(3)); + g_logger().info("Improve Save Kills: {}", g_game().getImproveSave(4)); g_globalEvents().execute(GLOBALEVENT_SHUTDOWN); // kick all players that are still online @@ -1518,11 +1522,6 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo return; } - if (!item->isPushable() || item->hasAttribute(ItemAttribute_t::UNIQUEID)) { - player->sendCancelMessage(RETURNVALUE_NOTMOVABLE); - return; - } - const Position &playerPos = player->getPosition(); auto cylinderTile = fromCylinder->getTile(); const Position &mapFromPos = cylinderTile ? cylinderTile->getPosition() : item->getPosition(); @@ -1649,12 +1648,17 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo return; } } - + if (isTryingToStow(toPos, toCylinder)) { player->stowItem(item, count, false); return; } - + + if (!item->isPushable() || item->hasAttribute(ItemAttribute_t::UNIQUEID)) { + player->sendCancelMessage(RETURNVALUE_NOTMOVABLE); + return; + } + ReturnValue ret = internalMoveItem(fromCylinder, toCylinder, toIndex, item, count, nullptr, 0, player); if (ret != RETURNVALUE_NOERROR) { player->sendCancelMessage(ret); diff --git a/src/game/game.hpp b/src/game/game.hpp index d70263c1775..fdc32375dad 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -25,6 +25,7 @@ #include "items/items_classification.hpp" #include "modal_window/modal_window.hpp" #include "enums/object_category.hpp" +#include "lib/logging/logger.hpp" // Forward declaration for protobuf class namespace Canary { @@ -717,6 +718,30 @@ class Game { std::vector getPublicAchievements(); std::map getAchievements(); + void addImproveSave(uint8_t x) { + if (x == 1) { + totalImproveSave++; + } else if (x == 2) { + totalImproveSaveStash++; + } else if (x == 3) { + totalImproveSaveSpells++; + } else if (x == 4) { + totalImproveSaveKills++; + } + } + int32_t getImproveSave(uint8_t x) { + if (x == 1) { + return totalImproveSave; + } else if (x == 2) { + return totalImproveSaveStash; + } else if (x == 3) { + return totalImproveSaveSpells; + } else if (x == 4) { + return totalImproveSaveKills; + } + return 0; + } + private: std::map m_achievements; std::map m_achievementsNameToId; @@ -944,6 +969,11 @@ class Game { std::string generateHighscoreQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation); std::string generateHighscoreOrGetCachedQueryForEntries(const std::string &categoryName, uint32_t page, uint8_t entriesPerPage, uint32_t vocation); std::string generateHighscoreOrGetCachedQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation); + + uint32_t totalImproveSave = 0; + uint32_t totalImproveSaveStash = 0; + uint32_t totalImproveSaveSpells = 0; + uint32_t totalImproveSaveKills = 0; }; constexpr auto g_game = Game::getInstance; diff --git a/src/game/scheduling/save_manager.cpp b/src/game/scheduling/save_manager.cpp index 2c1eff6657c..8e7cf65cc3b 100644 --- a/src/game/scheduling/save_manager.cpp +++ b/src/game/scheduling/save_manager.cpp @@ -14,6 +14,10 @@ SaveManager &SaveManager::getInstance() { void SaveManager::saveAll() { Benchmark bm_saveAll; logger.info("Saving server..."); + logger.info("Total save: {}", g_game().getImproveSave(1)); + logger.info("Improve Save Stash: {}", g_game().getImproveSave(2)); + logger.info("Improve Save Spells: {}", g_game().getImproveSave(3)); + logger.info("Improve Save Kills: {}", g_game().getImproveSave(4)); const auto players = game.getPlayers(); for (const auto &[_, player] : players) { diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp index d4a4f33774d..3fa98701c42 100644 --- a/src/io/functions/iologindata_load_player.cpp +++ b/src/io/functions/iologindata_load_player.cpp @@ -330,6 +330,8 @@ void IOLoginDataLoad::loadPlayerKills(std::shared_ptr player, DBResult_p time_t killTime = result->getNumber("time"); if ((time(nullptr) - killTime) <= g_configManager().getNumber(FRAG_TIME, __FUNCTION__)) { player->unjustifiedKills.emplace_back(result->getNumber("target"), killTime, result->getNumber("unavenged")); + } else { + player->setSaveUnjustifiedKills(true); } } while (result->next()); } @@ -399,6 +401,7 @@ void IOLoginDataLoad::loadPlayerStashItems(std::shared_ptr player, DBRes player->addItemOnStash(result->getNumber("item_id"), result->getNumber("item_count")); } while (result->next()); } + player->setSaveStash(false); } void IOLoginDataLoad::loadPlayerBestiaryCharms(std::shared_ptr player, DBResult_ptr result) { diff --git a/src/io/functions/iologindata_save_player.cpp b/src/io/functions/iologindata_save_player.cpp index 7bc1b34c864..c79c09c7bb1 100644 --- a/src/io/functions/iologindata_save_player.cpp +++ b/src/io/functions/iologindata_save_player.cpp @@ -340,6 +340,8 @@ bool IOLoginDataSave::savePlayerStash(std::shared_ptr player) { if (!stashQuery.execute()) { return false; } + + player->setSaveStash(false); return true; } @@ -369,6 +371,8 @@ bool IOLoginDataSave::savePlayerSpells(std::shared_ptr player) { if (!spellsQuery.execute()) { return false; } + + player->setSaveSpells(false); return true; } @@ -398,6 +402,8 @@ bool IOLoginDataSave::savePlayerKills(std::shared_ptr player) { if (!killsQuery.execute()) { return false; } + + player->setSaveUnjustifiedKills(false); return true; } diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp index 4c6b95dc32e..ee4f2e69a41 100644 --- a/src/io/iologindata.cpp +++ b/src/io/iologindata.cpp @@ -215,20 +215,31 @@ bool IOLoginData::savePlayerGuard(std::shared_ptr player) { throw DatabaseException("Player nullptr in function: " + std::string(__FUNCTION__)); } + g_game().addImproveSave(1); + if (!IOLoginDataSave::savePlayerFirst(player)) { throw DatabaseException("[" + std::string(__FUNCTION__) + "] - Failed to save player first: " + player->getName()); } - if (!IOLoginDataSave::savePlayerStash(player)) { - throw DatabaseException("[IOLoginDataSave::savePlayerFirst] - Failed to save player stash: " + player->getName()); + if (player->hasSaveStash()) { + if (!IOLoginDataSave::savePlayerStash(player)) { + throw DatabaseException("[IOLoginDataSave::savePlayerFirst] - Failed to save player stash: " + player->getName()); + } + g_game().addImproveSave(2); } - if (!IOLoginDataSave::savePlayerSpells(player)) { - throw DatabaseException("[IOLoginDataSave::savePlayerSpells] - Failed to save player spells: " + player->getName()); + if (player->hasSaveSpells()) { + if (!IOLoginDataSave::savePlayerSpells(player)) { + throw DatabaseException("[IOLoginDataSave::savePlayerSpells] - Failed to save player spells: " + player->getName()); + } + g_game().addImproveSave(3); } - if (!IOLoginDataSave::savePlayerKills(player)) { - throw DatabaseException("IOLoginDataSave::savePlayerKills] - Failed to save player kills: " + player->getName()); + if (player->hasSaveUnjustifiedKills()) { + if (!IOLoginDataSave::savePlayerKills(player)) { + throw DatabaseException("IOLoginDataSave::savePlayerKills] - Failed to save player kills: " + player->getName()); + } + g_game().addImproveSave(4); } if (!IOLoginDataSave::savePlayerBestiarySystem(player)) {