From 685e3afd3635525d342d33e4bd8578b6898bf9d2 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Fri, 22 Mar 2024 18:21:27 -0300 Subject: [PATCH 01/21] refactor: move codes from std::bind to lambda expressions (#2475) This modernizes our codebase by transitioning from std::bind to lambda expressions, aligning with modern C++ best practices to enhance readability, efficiency, and maintainability. This refactor simplifies syntax, taps into the compiler's ability to better optimize lambda expressions, and contributes to a cleaner, more straightforward code structure. Lambda expressions, being a pivotal feature of C++11 and beyond, offer improved code conciseness, performance benefits due to more effective compiler optimizations, and increased flexibility in handling local variable captures and inline code. By embracing these modern C++ features, we aim to bolster the quality and future development of our project, and we welcome the community's ongoing feedback and contributions to these efforts. --- src/creatures/combat/condition.cpp | 6 +- src/creatures/creature.cpp | 22 +- src/creatures/interactions/chat.cpp | 4 +- src/creatures/monsters/monster.cpp | 2 +- .../monsters/spawns/spawn_monster.cpp | 14 +- src/creatures/npcs/npc.cpp | 8 +- src/creatures/npcs/spawns/spawn_npc.cpp | 12 +- src/creatures/players/player.cpp | 14 +- src/game/game.cpp | 213 ++++++++---- src/items/bed.cpp | 4 +- src/items/decay/decay.cpp | 12 +- src/lua/creature/raids.cpp | 16 +- .../functions/core/game/global_functions.cpp | 2 +- src/lua/global/globalevent.cpp | 12 +- src/server/network/connection/connection.cpp | 39 ++- src/server/network/message/outputmessage.cpp | 5 +- src/server/network/protocol/protocolgame.cpp | 309 +++++++++--------- src/server/network/protocol/protocolgame.hpp | 6 - src/server/network/protocol/protocollogin.cpp | 6 +- .../network/protocol/protocolstatus.cpp | 11 +- src/server/server.cpp | 17 +- 21 files changed, 438 insertions(+), 296 deletions(-) diff --git a/src/creatures/combat/condition.cpp b/src/creatures/combat/condition.cpp index d54a3deb1d0..9d0f6962884 100644 --- a/src/creatures/combat/condition.cpp +++ b/src/creatures/combat/condition.cpp @@ -2041,7 +2041,11 @@ bool ConditionFeared::executeCondition(std::shared_ptr creature, int32 } if (getFleePath(creature, currentPos, listDir)) { - g_dispatcher().addEvent(std::bind(&Game::forcePlayerAutoWalk, &g_game(), creature->getID(), listDir.data()), "ConditionFeared::executeCondition"); + g_dispatcher().addEvent([id = creature->getID(), listDir = listDir.data()] { + g_game().forcePlayerAutoWalk(id, listDir); + }, + "ConditionFeared::executeCondition"); + g_logger().debug("[ConditionFeared::executeCondition] Walking Scheduled"); } } diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index d17ee454402..6ee605769a7 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -258,8 +258,8 @@ void Creature::addEventWalk(bool firstStep) { } self->eventWalk = g_dispatcher().scheduleEvent( - static_cast(ticks), std::bind(&Game::checkCreatureWalk, &g_game(), self->getID()), - "Creature::checkCreatureWalk" + static_cast(ticks), + [creatureId = self->getID()] { g_game().checkCreatureWalk(creatureId); }, "Creature::checkCreatureWalk" ); }); } @@ -600,7 +600,7 @@ void Creature::onCreatureMove(const std::shared_ptr &creature, const s if (followCreature && (creature == getCreature() || creature == followCreature)) { if (hasFollowPath) { isUpdatingPath = true; - g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, &g_game(), getID()), "Game::updateCreatureWalk"); + g_dispatcher().addEvent([creatureId = getID()] { g_game().updateCreatureWalk(creatureId); }, "Game::updateCreatureWalk"); } if (newPos.z != oldPos.z || !canSee(followCreature->getPosition())) { @@ -615,7 +615,7 @@ void Creature::onCreatureMove(const std::shared_ptr &creature, const s } else { if (hasExtraSwing()) { // our target is moving lets see if we can get in hit - g_dispatcher().addEvent(std::bind(&Game::checkCreatureAttack, &g_game(), getID()), "Game::checkCreatureAttack"); + g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, "Game::checkCreatureAttack"); } if (newTile->getZoneType() != oldTile->getZoneType()) { @@ -814,10 +814,10 @@ bool Creature::dropCorpse(std::shared_ptr lastHitCreature, std::shared } if (player->checkAutoLoot(monster->isRewardBoss()) && corpseContainer && mostDamageCreature->getPlayer()) { - g_dispatcher().addEvent( - std::bind(&Game::playerQuickLootCorpse, &g_game(), player, corpseContainer, corpse->getPosition()), - "Game::playerQuickLootCorpse" - ); + g_dispatcher().addEvent([player, corpseContainer, corpsePosition = corpse->getPosition()] { + g_game().playerQuickLootCorpse(player, corpseContainer, corpsePosition); + }, + "Game::playerQuickLootCorpse"); } } } @@ -861,7 +861,7 @@ void Creature::changeHealth(int32_t healthChange, bool sendHealthChange /* = tru g_game().addCreatureHealth(static_self_cast()); } if (health <= 0) { - g_dispatcher().addEvent(std::bind(&Game::executeDeath, &g_game(), getID()), "Game::executeDeath"); + g_dispatcher().addEvent([creatureId = getID()] { g_game().executeDeath(creatureId); }, "Game::executeDeath"); } } @@ -1401,9 +1401,7 @@ void Creature::removeCondition(ConditionType_t conditionType, ConditionId_t cond int32_t walkDelay = getWalkDelay(); if (walkDelay > 0) { g_dispatcher().scheduleEvent( - walkDelay, - std::bind(&Game::forceRemoveCondition, &g_game(), getID(), conditionType, conditionId), - "Game::forceRemoveCondition" + walkDelay, [creatureId = getID(), conditionType, conditionId] { g_game().forceRemoveCondition(creatureId, conditionType, conditionId); }, "Game::forceRemoveCondition" ); return; } diff --git a/src/creatures/interactions/chat.cpp b/src/creatures/interactions/chat.cpp index f30c3f219e3..e16af670fcc 100644 --- a/src/creatures/interactions/chat.cpp +++ b/src/creatures/interactions/chat.cpp @@ -81,7 +81,9 @@ bool ChatChannel::addUser(const std::shared_ptr &player) { if (id == CHANNEL_GUILD) { const auto guild = player->getGuild(); if (guild && !guild->getMotd().empty()) { - g_dispatcher().scheduleEvent(150, std::bind(&Game::sendGuildMotd, &g_game(), player->getID()), "Game::sendGuildMotd"); + g_dispatcher().scheduleEvent( + 150, [playerId = player->getID()] { g_game().sendGuildMotd(playerId); }, "Game::sendGuildMotd" + ); } } diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index 5f31c67aa72..f15616d6af5 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -668,7 +668,7 @@ bool Monster::selectTarget(const std::shared_ptr &creature) { if (isHostile() || isSummon()) { if (setAttackedCreature(creature)) { - g_dispatcher().addEvent(std::bind(&Game::checkCreatureAttack, &g_game(), getID()), "Game::checkCreatureAttack"); + g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, "Game::checkCreatureAttack"); } } return setFollowCreature(creature); diff --git a/src/creatures/monsters/spawns/spawn_monster.cpp b/src/creatures/monsters/spawns/spawn_monster.cpp index aec222d723a..5d9f386e25f 100644 --- a/src/creatures/monsters/spawns/spawn_monster.cpp +++ b/src/creatures/monsters/spawns/spawn_monster.cpp @@ -141,7 +141,9 @@ bool SpawnsMonster::isInZone(const Position ¢erPos, int32_t radius, const Po void SpawnMonster::startSpawnMonsterCheck() { if (checkSpawnMonsterEvent == 0) { - checkSpawnMonsterEvent = g_dispatcher().scheduleEvent(getInterval(), std::bind(&SpawnMonster::checkSpawnMonster, this), "SpawnMonster::checkSpawnMonster"); + checkSpawnMonsterEvent = g_dispatcher().scheduleEvent( + getInterval(), [this] { checkSpawnMonster(); }, "SpawnMonster::checkSpawnMonster" + ); } } @@ -225,7 +227,7 @@ void SpawnMonster::startup(bool delayed) { continue; } if (delayed) { - g_dispatcher().addEvent(std::bind(&SpawnMonster::scheduleSpawn, this, spawnMonsterId, sb, mType, 0, true), "SpawnMonster::startup"); + g_dispatcher().addEvent([this, spawnMonsterId, &sb, mType] { scheduleSpawn(spawnMonsterId, sb, mType, 0, true); }, "SpawnMonster::startup"); } else { scheduleSpawn(spawnMonsterId, sb, mType, 0, true); } @@ -265,7 +267,9 @@ void SpawnMonster::checkSpawnMonster() { } if (spawnedMonsterMap.size() < spawnMonsterMap.size()) { - checkSpawnMonsterEvent = g_dispatcher().scheduleEvent(getInterval(), std::bind(&SpawnMonster::checkSpawnMonster, this), "SpawnMonster::checkSpawnMonster"); + checkSpawnMonsterEvent = g_dispatcher().scheduleEvent( + getInterval(), [this] { checkSpawnMonster(); }, "SpawnMonster::checkSpawnMonster" + ); } } @@ -274,7 +278,9 @@ void SpawnMonster::scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, cons spawnMonster(spawnMonsterId, sb, mType, startup); } else { g_game().addMagicEffect(sb.pos, CONST_ME_TELEPORT); - g_dispatcher().scheduleEvent(NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, std::bind(&SpawnMonster::scheduleSpawn, this, spawnMonsterId, sb, mType, interval - NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, startup), "SpawnMonster::scheduleSpawn"); + g_dispatcher().scheduleEvent( + NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, [=, this, &sb] { scheduleSpawn(spawnMonsterId, sb, mType, interval - NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, startup); }, "SpawnMonster::scheduleSpawn" + ); } } diff --git a/src/creatures/npcs/npc.cpp b/src/creatures/npcs/npc.cpp index 0f9f60cec9b..d347ec6b66c 100644 --- a/src/creatures/npcs/npc.cpp +++ b/src/creatures/npcs/npc.cpp @@ -351,7 +351,9 @@ void Npc::onPlayerSellAllLoot(uint32_t playerId, uint16_t itemId, bool ignore, u return; } if (hasMore) { - g_dispatcher().scheduleEvent(SCHEDULER_MINTICKS, std::bind(&Npc::onPlayerSellAllLoot, this, player->getID(), itemId, ignore, totalPrice), __FUNCTION__); + g_dispatcher().scheduleEvent( + SCHEDULER_MINTICKS, [this, playerId = player->getID(), itemId, ignore, totalPrice] { onPlayerSellAllLoot(playerId, itemId, ignore, totalPrice); }, __FUNCTION__ + ); return; } ss << "You sold all of the items from your loot pouch for "; @@ -366,7 +368,9 @@ void Npc::onPlayerSellItem(std::shared_ptr player, uint16_t itemId, uint return; } if (itemId == ITEM_GOLD_POUCH) { - g_dispatcher().scheduleEvent(SCHEDULER_MINTICKS, std::bind(&Npc::onPlayerSellAllLoot, this, player->getID(), itemId, ignore, 0), __FUNCTION__); + g_dispatcher().scheduleEvent( + SCHEDULER_MINTICKS, [this, playerId = player->getID(), itemId, ignore] { onPlayerSellAllLoot(playerId, itemId, ignore, 0); }, __FUNCTION__ + ); return; } diff --git a/src/creatures/npcs/spawns/spawn_npc.cpp b/src/creatures/npcs/spawns/spawn_npc.cpp index 7fd99d6c37f..968deca5331 100644 --- a/src/creatures/npcs/spawns/spawn_npc.cpp +++ b/src/creatures/npcs/spawns/spawn_npc.cpp @@ -131,7 +131,9 @@ bool SpawnsNpc::isInZone(const Position ¢erPos, int32_t radius, const Positi void SpawnNpc::startSpawnNpcCheck() { if (checkSpawnNpcEvent == 0) { - checkSpawnNpcEvent = g_dispatcher().scheduleEvent(getInterval(), std::bind(&SpawnNpc::checkSpawnNpc, this), "SpawnNpc::checkSpawnNpc"); + checkSpawnNpcEvent = g_dispatcher().scheduleEvent( + getInterval(), [this] { checkSpawnNpc(); }, "SpawnNpc::checkSpawnNpc" + ); } } @@ -217,7 +219,9 @@ void SpawnNpc::checkSpawnNpc() { } if (spawnedNpcMap.size() < spawnNpcMap.size()) { - checkSpawnNpcEvent = g_dispatcher().scheduleEvent(getInterval(), std::bind(&SpawnNpc::checkSpawnNpc, this), __FUNCTION__); + checkSpawnNpcEvent = g_dispatcher().scheduleEvent( + getInterval(), [this] { checkSpawnNpc(); }, __FUNCTION__ + ); } } @@ -226,7 +230,9 @@ void SpawnNpc::scheduleSpawnNpc(uint32_t spawnId, spawnBlockNpc_t &sb, uint16_t spawnNpc(spawnId, sb.npcType, sb.pos, sb.direction); } else { g_game().addMagicEffect(sb.pos, CONST_ME_TELEPORT); - g_dispatcher().scheduleEvent(1400, std::bind(&SpawnNpc::scheduleSpawnNpc, this, spawnId, sb, interval - NONBLOCKABLE_SPAWN_NPC_INTERVAL), __FUNCTION__); + g_dispatcher().scheduleEvent( + 1400, [=, this, &sb] { scheduleSpawnNpc(spawnId, sb, interval - NONBLOCKABLE_SPAWN_NPC_INTERVAL); }, __FUNCTION__ + ); } } diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 874089e5602..76ca1755c70 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -1934,7 +1934,7 @@ void Player::onCreatureMove(const std::shared_ptr &creature, const std const auto &followCreature = getFollowCreature(); if (hasFollowPath && (creature == followCreature || (creature.get() == this && followCreature))) { isUpdatingPath = false; - g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, &g_game(), getID()), "Game::updateCreatureWalk"); + g_dispatcher().addEvent([creatureId = getID()] { g_game().updateCreatureWalk(creatureId); }, "Game::updateCreatureWalk"); } if (creature != getPlayer()) { @@ -4245,7 +4245,7 @@ bool Player::updateSaleShopList(std::shared_ptr item) { return true; } - g_dispatcher().addEvent(std::bind(&Game::updatePlayerSaleItems, &g_game(), getID()), "updatePlayerSaleItems"); + g_dispatcher().addEvent([creatureId = getID()] { g_game().updatePlayerSaleItems(creatureId); }, "Game::updatePlayerSaleItems"); scheduledSaleUpdate = true; return true; } @@ -4316,7 +4316,7 @@ bool Player::setAttackedCreature(std::shared_ptr creature) { } if (creature) { - g_dispatcher().addEvent(std::bind(&Game::checkCreatureAttack, &g_game(), getID()), "Game::checkCreatureAttack"); + g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, "Game::checkCreatureAttack"); } return true; } @@ -4376,7 +4376,11 @@ void Player::doAttacking(uint32_t) { result = Weapon::useFist(static_self_cast(), attackedCreature); } - std::shared_ptr task = createPlayerTask(std::max(SCHEDULER_MINTICKS, delay), std::bind(&Game::checkCreatureAttack, &g_game(), getID()), "Game::checkCreatureAttack"); + const auto &task = createPlayerTask( + std::max(SCHEDULER_MINTICKS, delay), + [playerId = getID()] { g_game().checkCreatureAttack(playerId); }, "Game::checkCreatureAttack" + ); + if (!classicSpeed) { setNextActionTask(task, false); } else { @@ -7776,7 +7780,7 @@ bool Player::canAutoWalk(const Position &toPosition, const std::function // Check if can walk to the toPosition and send event to use function stdext::arraylist listDir(128); if (getPathTo(toPosition, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, &g_game(), getID(), listDir.data()), __FUNCTION__); + g_dispatcher().addEvent([creatureId = getID(), dirs = listDir.data()] { g_game().playerAutoWalk(creatureId, dirs); }, __FUNCTION__); std::shared_ptr task = createPlayerTask(delay, function, __FUNCTION__); setNextWalkActionTask(task); diff --git a/src/game/game.cpp b/src/game/game.cpp index 7adaf196dff..c69b481e32c 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -342,17 +342,30 @@ void Game::start(ServiceManager* manager) { int minutes = tms->tm_min; lightHour = (minutes * LIGHT_DAY_LENGTH) / 60; - g_dispatcher().scheduleEvent(EVENT_MS + 1000, std::bind_front(&Game::createFiendishMonsters, this), "Game::createFiendishMonsters"); - g_dispatcher().scheduleEvent(EVENT_MS + 1000, std::bind_front(&Game::createInfluencedMonsters, this), "Game::createInfluencedMonsters"); - - g_dispatcher().cycleEvent(EVENT_MS, std::bind_front(&Game::updateForgeableMonsters, this), "Game::updateForgeableMonsters"); - g_dispatcher().cycleEvent(EVENT_LIGHTINTERVAL_MS, std::bind(&Game::checkLight, this), "Game::checkLight"); - g_dispatcher().cycleEvent(EVENT_CHECK_CREATURE_INTERVAL, std::bind(&Game::checkCreatures, this), "Game::checkCreatures"); - g_dispatcher().cycleEvent(EVENT_IMBUEMENT_INTERVAL, std::bind(&Game::checkImbuements, this), "Game::checkImbuements"); + g_dispatcher().scheduleEvent( + EVENT_MS + 1000, [this] { createFiendishMonsters(); }, "Game::createFiendishMonsters" + ); + g_dispatcher().scheduleEvent( + EVENT_MS + 1000, [this] { createInfluencedMonsters(); }, "Game::createInfluencedMonsters" + ); + g_dispatcher().cycleEvent( + EVENT_MS, [this] { updateForgeableMonsters(); }, "Game::updateForgeableMonsters" + ); + g_dispatcher().cycleEvent( + EVENT_LIGHTINTERVAL_MS, [this] { checkLight(); }, "Game::checkLight" + ); + g_dispatcher().cycleEvent( + EVENT_CHECK_CREATURE_INTERVAL, [this] { checkCreatures(); }, "Game::checkCreatures" + ); + g_dispatcher().cycleEvent( + EVENT_IMBUEMENT_INTERVAL, [this] { checkImbuements(); }, "Game::checkImbuements" + ); g_dispatcher().cycleEvent( EVENT_LUA_GARBAGE_COLLECTION, [this] { g_luaEnvironment().collectGarbage(); }, "Calling GC" ); - g_dispatcher().cycleEvent(EVENT_REFRESH_MARKET_PRICES, std::bind_front(&Game::loadItemsPrice, this), "Game::loadItemsPrice"); + g_dispatcher().cycleEvent( + EVENT_REFRESH_MARKET_PRICES, [this] { loadItemsPrice(); }, "Game::loadItemsPrice" + ); } GameState_t Game::getGameState() const { @@ -418,7 +431,7 @@ void Game::setGameState(GameState_t newState) { saveMotdNum(); g_saveManager().saveAll(); - g_dispatcher().addEvent(std::bind(&Game::shutdown, this), "Game::shutdown"); + g_dispatcher().addEvent([this] { shutdown(); }, "Game::shutdown"); break; } @@ -1165,9 +1178,11 @@ void Game::playerMoveThing(uint32_t playerId, const Position &fromPos, uint16_t } if (Position::areInRange<1, 1, 0>(movingCreature->getPosition(), player->getPosition())) { - std::shared_ptr task = createPlayerTask( + const auto &task = createPlayerTask( g_configManager().getNumber(PUSH_DELAY, __FUNCTION__), - std::bind(&Game::playerMoveCreatureByID, this, player->getID(), movingCreature->getID(), movingCreature->getPosition(), tile->getPosition()), + [this, player, movingCreature, tile] { + playerMoveCreatureByID(player->getID(), movingCreature->getID(), movingCreature->getPosition(), tile->getPosition()); + }, "Game::playerMoveCreatureByID" ); player->setNextActionPushTask(task); @@ -1208,8 +1223,9 @@ void Game::playerMoveCreatureByID(uint32_t playerId, uint32_t movingCreatureId, void Game::playerMoveCreature(std::shared_ptr player, std::shared_ptr movingCreature, const Position &movingCreatureOrigPos, std::shared_ptr toTile) { metrics::method_latency measure(__METHOD_NAME__); if (!player->canDoAction()) { - uint32_t delay = 600; - std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerMoveCreatureByID, this, player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()), "Game::playerMoveCreatureByID"); + const auto &task = createPlayerTask( + 600, [this, player, movingCreature, toTile, movingCreatureOrigPos] { playerMoveCreatureByID(player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()); }, "Game::playerMoveCreatureByID" + ); player->setNextActionPushTask(task); return; @@ -1221,10 +1237,10 @@ void Game::playerMoveCreature(std::shared_ptr player, std::shared_ptr listDir(128); if (player->getPathTo(movingCreatureOrigPos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); - - std::shared_ptr task = createPlayerTask(600, std::bind(&Game::playerMoveCreatureByID, this, player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()), "Game::playerMoveCreatureByID"); - + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); + const auto &task = createPlayerTask( + 600, [this, player, movingCreature, toTile, movingCreatureOrigPos] { playerMoveCreatureByID(player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()); }, "Game::playerMoveCreatureByID" + ); player->pushEvent(true); player->setNextActionPushTask(task); } else { @@ -1424,7 +1440,12 @@ void Game::playerMoveItemByPlayerID(uint32_t playerId, const Position &fromPos, void Game::playerMoveItem(std::shared_ptr player, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count, std::shared_ptr item, std::shared_ptr toCylinder) { if (!player->canDoAction()) { uint32_t delay = player->getNextActionTime(); - std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerMoveItemByPlayerID, this, player->getID(), fromPos, itemId, fromStackPos, toPos, count), "Game::playerMoveItemByPlayerID"); + std::shared_ptr task = createPlayerTask( + delay, [this, playerId = player->getID(), fromPos, itemId, fromStackPos, toPos, count] { + playerMoveItemByPlayerID(playerId, fromPos, itemId, fromStackPos, toPos, count); + }, + "Game::playerMoveItemByPlayerID" + ); player->setNextActionTask(task); return; } @@ -1519,9 +1540,14 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo // need to walk to the item first before using it stdext::arraylist listDir(128); if (player->getPathTo(item->getPosition(), listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this, player->getID(), fromPos, itemId, fromStackPos, toPos, count), "Game::playerMoveItemByPlayerID"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId = player->getID(), fromPos, itemId, fromStackPos, toPos, count] { + playerMoveItemByPlayerID(playerId, fromPos, itemId, fromStackPos, toPos, count); + }, + "Game::playerMoveItemByPlayerID" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -1576,9 +1602,14 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo stdext::arraylist listDir(128); if (player->getPathTo(walkPos, listDir, 0, 0, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); - - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this, player->getID(), itemPos, itemId, itemStackPos, toPos, count), "Game::playerMoveItemByPlayerID"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); + + std::shared_ptr task = createPlayerTask( + 400, [this, playerId = player->getID(), itemPos, itemId, itemStackPos, toPos, count] { + playerMoveItemByPlayerID(playerId, itemPos, itemId, itemStackPos, toPos, count); + }, + "Game::playerMoveItemByPlayerID" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -3484,9 +3515,11 @@ void Game::playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t f stdext::arraylist listDir(128); if (player->getPathTo(walkToPos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseItemEx, this, playerId, itemPos, itemStackPos, fromItemId, toPos, toStackPos, toItemId), "Game::playerUseItemEx"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, itemPos, itemStackPos, fromItemId, toPos, toStackPos, toItemId] { playerUseItemEx(playerId, itemPos, itemStackPos, fromItemId, toPos, toStackPos, toItemId); }, "Game::playerUseItemEx" + ); if (it.isRune() || it.type == ITEM_TYPE_POTION) { player->setNextPotionActionTask(task); } else { @@ -3512,7 +3545,9 @@ void Game::playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t f if (it.isRune() || it.type == ITEM_TYPE_POTION) { delay = player->getNextPotionActionTime(); } - std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerUseItemEx, this, playerId, fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId), "Game::playerUseItemEx"); + std::shared_ptr task = createPlayerTask( + delay, [this, playerId, fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId] { playerUseItemEx(playerId, fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId); }, "Game::playerUseItemEx" + ); if (it.isRune() || it.type == ITEM_TYPE_POTION) { player->setNextPotionActionTask(task); } else { @@ -3594,9 +3629,11 @@ void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPo if (ret == RETURNVALUE_TOOFARAWAY) { stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseItem, this, playerId, pos, stackPos, index, itemId), "Game::playerUseItem"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, pos, stackPos, index, itemId] { playerUseItem(playerId, pos, stackPos, index, itemId); }, "Game::playerUseItem" + ); if (it.isRune() || it.type == ITEM_TYPE_POTION) { player->setNextPotionActionTask(task); } else { @@ -3622,7 +3659,9 @@ void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPo if (it.isRune() || it.type == ITEM_TYPE_POTION) { delay = player->getNextPotionActionTime(); } - std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerUseItem, this, playerId, pos, stackPos, index, itemId), "Game::playerUseItem"); + std::shared_ptr task = createPlayerTask( + delay, [this, playerId, pos, stackPos, index, itemId] { playerUseItem(playerId, pos, stackPos, index, itemId); }, "Game::playerUseItem" + ); if (it.isRune() || it.type == ITEM_TYPE_POTION) { player->setNextPotionActionTask(task); } else { @@ -3734,9 +3773,14 @@ void Game::playerUseWithCreature(uint32_t playerId, const Position &fromPos, uin stdext::arraylist listDir(128); if (player->getPathTo(walkToPos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); - - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseWithCreature, this, playerId, itemPos, itemStackPos, creatureId, itemId), "Game::playerUseWithCreature"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); + + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, itemPos, itemStackPos, creatureId, itemId] { + playerUseWithCreature(playerId, itemPos, itemStackPos, creatureId, itemId); + }, + "Game::playerUseWithCreature" + ); if (it.isRune() || it.type == ITEM_TYPE_POTION) { player->setNextPotionActionTask(task); } else { @@ -3762,7 +3806,9 @@ void Game::playerUseWithCreature(uint32_t playerId, const Position &fromPos, uin if (it.isRune() || it.type == ITEM_TYPE_POTION) { delay = player->getNextPotionActionTime(); } - std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerUseWithCreature, this, playerId, fromPos, fromStackPos, creatureId, itemId), "Game::playerUseWithCreature"); + std::shared_ptr task = createPlayerTask( + delay, [this, playerId, fromPos, fromStackPos, creatureId, itemId] { playerUseWithCreature(playerId, fromPos, fromStackPos, creatureId, itemId); }, "Game::playerUseWithCreature" + ); if (it.isRune() || it.type == ITEM_TYPE_POTION) { player->setNextPotionActionTask(task); @@ -3888,9 +3934,14 @@ void Game::playerRotateItem(uint32_t playerId, const Position &pos, uint8_t stac if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) { stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerRotateItem, this, playerId, pos, stackPos, itemId), "Game::playerRotateItem"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, pos, stackPos, itemId] { + playerRotateItem(playerId, pos, stackPos, itemId); + }, + "Game::playerRotateItem" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -3939,12 +3990,16 @@ void Game::playerConfigureShowOffSocket(uint32_t playerId, const Position &pos, if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) { stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, false)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); std::shared_ptr task; if (isPodiumOfRenown) { - task = createPlayerTask(400, std::bind_front(&Player::sendPodiumWindow, player, item, pos, itemId, stackPos), "Game::playerConfigureShowOffSocket"); + task = createPlayerTask( + 400, [player, item, pos, itemId, stackPos] { player->sendPodiumWindow(item, pos, itemId, stackPos); }, "Game::playerConfigureShowOffSocket" + ); } else { - task = createPlayerTask(400, std::bind_front(&Player::sendMonsterPodiumWindow, player, item, pos, itemId, stackPos), "Game::playerConfigureShowOffSocket"); + task = createPlayerTask( + 400, [player, item, pos, itemId, stackPos] { player->sendMonsterPodiumWindow(item, pos, itemId, stackPos); }, "Game::playerConfigureShowOffSocket" + ); } player->setNextWalkActionTask(task); } else { @@ -3996,8 +4051,10 @@ void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Pos if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) { stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, false)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, pos] { playerBrowseField(playerId, pos); }, "Game::playerBrowseField" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -4135,9 +4192,11 @@ void Game::playerWrapableItem(uint32_t playerId, const Position &pos, uint8_t st if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) { stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerWrapableItem, this, playerId, pos, stackPos, itemId), "Game::playerWrapableItem"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, pos, stackPos, itemId] { playerWrapableItem(playerId, pos, stackPos, itemId); }, "Game::playerWrapableItem" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -4314,8 +4373,10 @@ void Game::playerBrowseField(uint32_t playerId, const Position &pos) { if (!Position::areInRange<1, 1>(playerPos, pos)) { stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, pos] { playerBrowseField(playerId, pos); }, "Game::playerBrowseField" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -4575,9 +4636,11 @@ void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t st if (!Position::areInRange<1, 1>(tradeItemPosition, playerPosition)) { stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerRequestTrade, this, playerId, pos, stackPos, tradePlayerId, itemId), "Game::playerRequestTrade"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, pos, stackPos, tradePlayerId, itemId] { playerRequestTrade(playerId, pos, stackPos, tradePlayerId, itemId); }, "Game::playerRequestTrade" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -5120,7 +5183,12 @@ void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t item if (!autoLoot && !player->canDoAction()) { uint32_t delay = player->getNextActionTime(); - std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerQuickLoot, this, player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot), "Game::playerQuickLoot"); + std::shared_ptr task = createPlayerTask( + delay, [this, playerId = player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot] { + playerQuickLoot(playerId, pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot); + }, + "Game::playerQuickLoot" + ); player->setNextActionTask(task); return; } @@ -5130,8 +5198,13 @@ void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t item // need to walk to the corpse first before looting it stdext::arraylist listDir(128); if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(0, std::bind(&Game::playerQuickLoot, this, player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot), "Game::playerQuickLoot"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); + std::shared_ptr task = createPlayerTask( + 0, [this, playerId = player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot] { + playerQuickLoot(playerId, pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot); + }, + "Game::playerQuickLoot" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -5494,7 +5567,7 @@ void Game::playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId) { } player->setAttackedCreature(attackCreature); - g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, this, player->getID()), "Game::updateCreatureWalk"); + g_dispatcher().addEvent([this, plyerId = player->getID()] { updateCreatureWalk(plyerId); }, "Game::updateCreatureWalk"); } void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) { @@ -5504,7 +5577,7 @@ void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) { } player->setAttackedCreature(nullptr); - g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, this, player->getID()), "Game::updateCreatureWalk"); + g_dispatcher().addEvent([this, plyerId = player->getID()] { updateCreatureWalk(plyerId); }, "Game::updateCreatureWalk"); player->setFollowCreature(getCreatureByID(creatureId)); } @@ -6252,7 +6325,6 @@ bool Game::combatBlockHit(CombatDamage &damage, std::shared_ptr attack std::shared_ptr targetPlayer = target->getPlayer(); if (damage.primary.type != COMBAT_NONE) { - damage.primary.value = -damage.primary.value; // Damage healing primary if (attacker) { @@ -9330,8 +9402,10 @@ void Game::playerSetMonsterPodium(uint32_t playerId, uint32_t monsterRaceId, con if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) { if (stdext::arraylist listDir(128); player->getPathTo(pos, listDir, 0, 1, true, false)) { - g_dispatcher().addEvent(std::bind_front(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); - std::shared_ptr task = createPlayerTask(400, std::bind_front(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, pos] { playerBrowseField(playerId, pos); }, "Game::playerBrowseField" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -9428,9 +9502,13 @@ void Game::playerRotatePodium(uint32_t playerId, const Position &pos, uint8_t st if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) { if (stdext::arraylist listDir(128); player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher().addEvent(std::bind_front(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk"); - - std::shared_ptr task = createPlayerTask(400, std::bind_front(&Game::playerRotatePodium, this, playerId, pos, stackPos, itemId), "Game::playerRotatePodium"); + g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk"); + std::shared_ptr task = createPlayerTask( + 400, [this, playerId, pos, stackPos, itemId] { + playerRotatePodium(playerId, pos, stackPos, itemId); + }, + "Game::playerRotatePodium" + ); player->setNextWalkActionTask(task); } else { player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); @@ -9947,7 +10025,7 @@ uint32_t Game::makeFiendishMonster(uint32_t forgeableMonsterId /* = 0*/, bool cr auto schedulerTask = createPlayerTask( finalTime, - std::bind_front(&Game::updateFiendishMonsterStatus, this, monster->getID(), monster->getName()), + [this, monster] { updateFiendishMonsterStatus(monster->getID(), monster->getName()); }, "Game::updateFiendishMonsterStatus" ); forgeMonsterEventIds[monster->getID()] = g_dispatcher().scheduleEvent(schedulerTask); @@ -9986,7 +10064,9 @@ bool Game::removeInfluencedMonster(uint32_t id, bool create /* = false*/) { influencedMonsters.erase(find); if (create) { - g_dispatcher().scheduleEvent(200 * 1000, std::bind_front(&Game::makeInfluencedMonster, this), "Game::makeInfluencedMonster"); + g_dispatcher().scheduleEvent( + 200 * 1000, [this] { makeInfluencedMonster(); }, "Game::makeInfluencedMonster" + ); } } else { g_logger().warn("[Game::removeInfluencedMonster] - Failed to remove a Influenced Monster, error code: monster id not exist in the influenced monsters map"); @@ -10002,7 +10082,9 @@ bool Game::removeFiendishMonster(uint32_t id, bool create /* = true*/) { checkForgeEventId(id); if (create) { - g_dispatcher().scheduleEvent(300 * 1000, std::bind_front(&Game::makeFiendishMonster, this, 0, false), "Game::makeFiendishMonster"); + g_dispatcher().scheduleEvent( + 300 * 1000, [this] { makeFiendishMonster(0, false); }, "Game::makeFiendishMonster" + ); } } else { g_logger().warn("[Game::removeFiendishMonster] - Failed to remove a Fiendish Monster, error code: monster id not exist in the fiendish monsters map"); @@ -10200,7 +10282,9 @@ void Game::playerCheckActivity(const std::string &playerName, int interval) { } } - g_dispatcher().scheduleEvent(1000, std::bind(&Game::playerCheckActivity, this, playerName, interval), "Game::playerCheckActivity"); + g_dispatcher().scheduleEvent( + 1000, [this, playerName, interval] { playerCheckActivity(playerName, interval); }, "Game::playerCheckActivity" + ); } void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackPos, uint32_t maxMoveItems /* = 0*/) { @@ -10221,8 +10305,11 @@ void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint return; } - if (auto function = std::bind(&Game::playerRewardChestCollect, this, player->getID(), pos, itemId, stackPos, maxMoveItems); - player->canAutoWalk(item->getPosition(), function)) { + const auto &function = [this, playerId = player->getID(), pos, itemId, stackPos, maxMoveItems] { + playerRewardChestCollect(playerId, pos, itemId, stackPos, maxMoveItems); + }; + + if (player->canAutoWalk(item->getPosition(), function)) { return; } diff --git a/src/items/bed.cpp b/src/items/bed.cpp index 4ce4a1e0edd..d093dcc5fd9 100644 --- a/src/items/bed.cpp +++ b/src/items/bed.cpp @@ -165,7 +165,9 @@ bool BedItem::sleep(std::shared_ptr player) { g_game().addMagicEffect(player->getPosition(), CONST_ME_SLEEP); // logout player after he sees himself walk onto the bed and it change id - g_dispatcher().scheduleEvent(SCHEDULER_MINTICKS, std::bind(&ProtocolGame::logout, player->client, false, false), "ProtocolGame::logout"); + g_dispatcher().scheduleEvent( + SCHEDULER_MINTICKS, [client = player->client] { client->logout(false, false); }, "ProtocolGame::logout" + ); // change self and partner's appearance updateAppearance(player); diff --git a/src/items/decay/decay.cpp b/src/items/decay/decay.cpp index 27ae7b6b485..848acffbf68 100644 --- a/src/items/decay/decay.cpp +++ b/src/items/decay/decay.cpp @@ -47,11 +47,15 @@ void Decay::startDecay(std::shared_ptr item) { int64_t timestamp = OTSYS_TIME() + duration; if (decayMap.empty()) { - eventId = g_dispatcher().scheduleEvent(std::max(SCHEDULER_MINTICKS, duration), std::bind(&Decay::checkDecay, this), "Decay::checkDecay"); + eventId = g_dispatcher().scheduleEvent( + std::max(SCHEDULER_MINTICKS, duration), [this] { checkDecay(); }, "Decay::checkDecay" + ); } else { if (timestamp < decayMap.begin()->first) { g_dispatcher().stopEvent(eventId); - eventId = g_dispatcher().scheduleEvent(std::max(SCHEDULER_MINTICKS, duration), std::bind(&Decay::checkDecay, this), "Decay::checkDecay"); + eventId = g_dispatcher().scheduleEvent( + std::max(SCHEDULER_MINTICKS, duration), [this] { checkDecay(); }, "Decay::checkDecay" + ); } } @@ -138,7 +142,9 @@ void Decay::checkDecay() { } if (it != end) { - eventId = g_dispatcher().scheduleEvent(std::max(SCHEDULER_MINTICKS, static_cast(it->first - timestamp)), std::bind(&Decay::checkDecay, this), "Decay::checkDecay"); + eventId = g_dispatcher().scheduleEvent( + std::max(SCHEDULER_MINTICKS, static_cast(it->first - timestamp)), [this] { checkDecay(); }, "Decay::checkDecay" + ); } } diff --git a/src/lua/creature/raids.cpp b/src/lua/creature/raids.cpp index f0d7cecf402..a4500d126ba 100644 --- a/src/lua/creature/raids.cpp +++ b/src/lua/creature/raids.cpp @@ -102,7 +102,9 @@ bool Raids::startup() { setLastRaidEnd(OTSYS_TIME()); - checkRaidsEvent = g_dispatcher().scheduleEvent(CHECK_RAIDS_INTERVAL * 1000, std::bind(&Raids::checkRaids, this), "Raids::checkRaids"); + checkRaidsEvent = g_dispatcher().scheduleEvent( + CHECK_RAIDS_INTERVAL * 1000, [this] { checkRaids(); }, "Raids::checkRaids" + ); started = true; return started; @@ -134,7 +136,9 @@ void Raids::checkRaids() { } } - checkRaidsEvent = g_dispatcher().scheduleEvent(CHECK_RAIDS_INTERVAL * 1000, std::bind(&Raids::checkRaids, this), "Raids::checkRaids"); + checkRaidsEvent = g_dispatcher().scheduleEvent( + CHECK_RAIDS_INTERVAL * 1000, [this] { checkRaids(); }, "Raids::checkRaids" + ); } void Raids::clear() { @@ -216,7 +220,9 @@ void Raid::startRaid() { const auto raidEvent = getNextRaidEvent(); if (raidEvent) { state = RAIDSTATE_EXECUTING; - nextEventEvent = g_dispatcher().scheduleEvent(raidEvent->getDelay(), std::bind(&Raid::executeRaidEvent, this, raidEvent), "Raid::executeRaidEvent"); + nextEventEvent = g_dispatcher().scheduleEvent( + raidEvent->getDelay(), [this, raidEvent] { executeRaidEvent(raidEvent); }, "Raid::executeRaidEvent" + ); } else { g_logger().warn("[raids] Raid {} has no events", name); resetRaid(); @@ -230,7 +236,9 @@ void Raid::executeRaidEvent(const std::shared_ptr raidEvent) { if (newRaidEvent) { uint32_t ticks = static_cast(std::max(RAID_MINTICKS, newRaidEvent->getDelay() - raidEvent->getDelay())); - nextEventEvent = g_dispatcher().scheduleEvent(ticks, std::bind(&Raid::executeRaidEvent, this, newRaidEvent), __FUNCTION__); + nextEventEvent = g_dispatcher().scheduleEvent( + ticks, [this, newRaidEvent] { executeRaidEvent(newRaidEvent); }, __FUNCTION__ + ); } else { resetRaid(); } diff --git a/src/lua/functions/core/game/global_functions.cpp b/src/lua/functions/core/game/global_functions.cpp index cbb133211f8..0403e88dd95 100644 --- a/src/lua/functions/core/game/global_functions.cpp +++ b/src/lua/functions/core/game/global_functions.cpp @@ -664,7 +664,7 @@ int GlobalFunctions::luaAddEvent(lua_State* L) { auto &lastTimerEventId = g_luaEnvironment().lastEventTimerId; eventDesc.eventId = g_dispatcher().scheduleEvent( delay, - std::bind(&LuaEnvironment::executeTimerEvent, &g_luaEnvironment(), lastTimerEventId), + [lastTimerEventId] { g_luaEnvironment().executeTimerEvent(lastTimerEventId); }, "LuaEnvironment::executeTimerEvent" ); diff --git a/src/lua/global/globalevent.cpp b/src/lua/global/globalevent.cpp index 62650b429a9..9626173dc9f 100644 --- a/src/lua/global/globalevent.cpp +++ b/src/lua/global/globalevent.cpp @@ -35,7 +35,9 @@ bool GlobalEvents::registerLuaEvent(const std::shared_ptr globalEve auto result = timerMap.emplace(globalEvent->getName(), globalEvent); if (result.second) { if (timerEventId == 0) { - timerEventId = g_dispatcher().scheduleEvent(SCHEDULER_MINTICKS, std::bind(&GlobalEvents::timer, this), "GlobalEvents::timer"); + timerEventId = g_dispatcher().scheduleEvent( + SCHEDULER_MINTICKS, [this] { timer(); }, "GlobalEvents::timer" + ); } return true; } @@ -99,7 +101,9 @@ void GlobalEvents::timer() { } if (nextScheduledTime != std::numeric_limits::max()) { - timerEventId = g_dispatcher().scheduleEvent(std::max(1000, nextScheduledTime * 1000), std::bind(&GlobalEvents::timer, this), __FUNCTION__); + timerEventId = g_dispatcher().scheduleEvent( + std::max(1000, nextScheduledTime * 1000), [this] { timer(); }, __FUNCTION__ + ); } } @@ -136,7 +140,9 @@ void GlobalEvents::think() { if (nextScheduledTime != std::numeric_limits::max()) { auto delay = static_cast(nextScheduledTime); - thinkEventId = g_dispatcher().scheduleEvent(delay, std::bind(&GlobalEvents::think, this), "GlobalEvents::think"); + thinkEventId = g_dispatcher().scheduleEvent( + delay, [this] { think(); }, "GlobalEvents::think" + ); } } diff --git a/src/server/network/connection/connection.cpp b/src/server/network/connection/connection.cpp index 41789b88387..cc27eb0e9eb 100644 --- a/src/server/network/connection/connection.cpp +++ b/src/server/network/connection/connection.cpp @@ -62,7 +62,7 @@ void Connection::close(bool force) { connectionState = CONNECTION_STATE_CLOSED; if (protocol) { - g_dispatcher().addEvent(std::bind_front(&Protocol::release, protocol), "Protocol::release", std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count()); + g_dispatcher().addEvent([protocol = protocol] { protocol->release(); }, "Protocol::release", std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count()); } if (messageQueue.empty() || force) { @@ -98,19 +98,23 @@ void Connection::closeSocket() { void Connection::accept(Protocol_ptr protocolPtr) { connectionState = CONNECTION_STATE_IDENTIFYING; protocol = std::move(protocolPtr); - g_dispatcher().addEvent(std::bind_front(&Protocol::onConnect, protocol), "Protocol::onConnect", std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count()); + g_dispatcher().addEvent([protocol = protocol] { protocol->onConnect(); }, "Protocol::onConnect", std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count()); acceptInternal(false); } void Connection::acceptInternal(bool toggleParseHeader) { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1)); + readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); try { - auto readCallback = toggleParseHeader ? std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1) - : std::bind(&Connection::parseProxyIdentification, shared_from_this(), std::placeholders::_1); - asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), readCallback); + asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), [self = shared_from_this(), toggleParseHeader](const std::error_code &error, std::size_t N) { + if (toggleParseHeader) { + self->parseHeader(error); + } else { + self->parseProxyIdentification(error); + } + }); } catch (const std::system_error &e) { g_logger().error("[Connection::acceptInternal] - Exception in async_read: {}", e.what()); close(FORCE_CLOSE); @@ -143,10 +147,10 @@ void Connection::parseProxyIdentification(const std::error_code &error) { connectionState = CONNECTION_STATE_READINGS; try { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1)); + readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); // Read the remainder of proxy identification - asio::async_read(socket, asio::buffer(msg.getBuffer(), remainder), std::bind(&Connection::parseProxyIdentification, shared_from_this(), std::placeholders::_1)); + asio::async_read(socket, asio::buffer(msg.getBuffer(), remainder), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parseProxyIdentification(error); }); } catch (const std::system_error &e) { g_logger().error("Connection::parseProxyIdentification] - error: {}", e.what()); close(FORCE_CLOSE); @@ -204,11 +208,12 @@ void Connection::parseHeader(const std::error_code &error) { try { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1)); + readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); // Read packet content msg.setLength(size + HEADER_LENGTH); - asio::async_read(socket, asio::buffer(msg.getBodyBuffer(), size), std::bind(&Connection::parsePacket, shared_from_this(), std::placeholders::_1)); + // Read the remainder of proxy identification + asio::async_read(socket, asio::buffer(msg.getBodyBuffer(), size), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parsePacket(error); }); } catch (const std::system_error &e) { g_logger().error("[Connection::parseHeader] - error: {}", e.what()); close(FORCE_CLOSE); @@ -270,11 +275,11 @@ void Connection::parsePacket(const std::error_code &error) { try { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1)); + readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); if (!skipReadingNextPacket) { // Wait to the next packet - asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)); + asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parseHeader(error); }); } } catch (const std::system_error &e) { g_logger().error("[Connection::parsePacket] - error: {}", e.what()); @@ -284,10 +289,10 @@ void Connection::parsePacket(const std::error_code &error) { void Connection::resumeWork() { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1)); + readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); try { - asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)); + asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parseHeader(error); }); } catch (const std::system_error &e) { g_logger().error("[Connection::resumeWork] - Exception in async_read: {}", e.what()); close(FORCE_CLOSE); @@ -306,7 +311,7 @@ void Connection::send(const OutputMessage_ptr &outputMessage) { if (noPendingWrite) { if (socket.is_open()) { try { - asio::post(socket.get_executor(), std::bind(&Connection::internalWorker, shared_from_this())); + asio::post(socket.get_executor(), [self = shared_from_this()] { self->internalWorker(); }); } catch (const std::system_error &e) { g_logger().error("[Connection::send] - Exception in posting write operation: {}", e.what()); close(FORCE_CLOSE); @@ -353,10 +358,10 @@ uint32_t Connection::getIP() { void Connection::internalSend(const OutputMessage_ptr &outputMessage) { writeTimer.expires_from_now(std::chrono::seconds(CONNECTION_WRITE_TIMEOUT)); - writeTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1)); + readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); try { - asio::async_write(socket, asio::buffer(outputMessage->getOutputBuffer(), outputMessage->getLength()), std::bind(&Connection::onWriteOperation, shared_from_this(), std::placeholders::_1)); + asio::async_write(socket, asio::buffer(outputMessage->getOutputBuffer(), outputMessage->getLength()), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->onWriteOperation(error); }); } catch (const std::system_error &e) { g_logger().error("[Connection::internalSend] - Exception in async_write: {}", e.what()); close(FORCE_CLOSE); diff --git a/src/server/network/message/outputmessage.cpp b/src/server/network/message/outputmessage.cpp index 6ede36da406..efed7fe8367 100644 --- a/src/server/network/message/outputmessage.cpp +++ b/src/server/network/message/outputmessage.cpp @@ -16,8 +16,9 @@ const std::chrono::milliseconds OUTPUTMESSAGE_AUTOSEND_DELAY { 10 }; void OutputMessagePool::scheduleSendAll() { - auto function = std::bind_front(&OutputMessagePool::sendAll, this); - g_dispatcher().scheduleEvent(OUTPUTMESSAGE_AUTOSEND_DELAY.count(), function, "OutputMessagePool::sendAll"); + g_dispatcher().scheduleEvent( + OUTPUTMESSAGE_AUTOSEND_DELAY.count(), [this] { sendAll(); }, "OutputMessagePool::sendAll" + ); } void OutputMessagePool::sendAll() { diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 5398155067e..218fc857d3c 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -248,16 +248,6 @@ ProtocolGame::ProtocolGame(Connection_ptr initConnection) : version = CLIENT_VERSION; } -template -void ProtocolGame::addGameTask(Callable function, Args &&... args) { - g_dispatcher().addEvent(std::bind(function, &g_game(), std::forward(args)...), "ProtocolGame::addGameTask"); -} - -template -void ProtocolGame::addGameTaskTimed(uint32_t delay, std::string_view context, Callable function, Args &&... args) { - g_dispatcher().addEvent(std::bind(function, &g_game(), std::forward(args)...), context, delay); -} - void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint8_t tier) { const ItemType &it = Item::items[id]; @@ -629,7 +619,10 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS foundPlayer->disconnect(); foundPlayer->isConnecting = true; - eventConnect = g_dispatcher().scheduleEvent(1000, std::bind(&ProtocolGame::connect, getThis(), foundPlayer->getName(), operatingSystem), "ProtocolGame::connect"); + eventConnect = g_dispatcher().scheduleEvent( + 1000, + [self = getThis(), playerName = foundPlayer->getName(), operatingSystem] { self->connect(playerName, operatingSystem); }, "ProtocolGame::connect" + ); } else { connect(foundPlayer->getName(), operatingSystem); } @@ -842,11 +835,13 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { output->addByte(0x14); output->addString(ss.str(), "ProtocolGame::onRecvFirstMessage - ss.str()"); send(output); - g_dispatcher().scheduleEvent(1000, std::bind(&ProtocolGame::disconnect, getThis()), "ProtocolGame::disconnect"); + g_dispatcher().scheduleEvent( + 1000, [self = getThis()] { self->disconnect(); }, "ProtocolGame::disconnect" + ); return; } - g_dispatcher().addEvent(std::bind(&ProtocolGame::login, getThis(), characterName, accountId, operatingSystem), "ProtocolGame::login"); + g_dispatcher().addEvent([self = getThis(), characterName, accountId, operatingSystem] { self->login(characterName, accountId, operatingSystem); }, "ProtocolGame::login"); } void ProtocolGame::onConnect() { @@ -907,20 +902,20 @@ void ProtocolGame::parsePacket(NetworkMessage &msg) { if (player->isDead() || player->getHealth() <= 0) { // Check player activity on death screen if (m_playerDeathTime == 0) { - addGameTask(&Game::playerCheckActivity, player->getName(), 1000); + g_game().playerCheckActivity(player->getName(), 1000); m_playerDeathTime++; } - g_dispatcher().addEvent(std::bind(&ProtocolGame::parsePacketDead, getThis(), recvbyte), "ProtocolGame::parsePacketDead"); + parsePacketDead(recvbyte); return; } // Modules system if (player && recvbyte != 0xD3) { - g_dispatcher().addEvent(std::bind(&Modules::executeOnRecvbyte, &g_modules(), player->getID(), msg, recvbyte), "Modules::executeOnRecvbyte"); + g_modules().executeOnRecvbyte(player->getID(), msg, recvbyte); } - g_dispatcher().addEvent(std::bind(&ProtocolGame::parsePacketFromDispatcher, getThis(), msg, recvbyte), "ProtocolGame::parsePacketFromDispatcher"); + parsePacketFromDispatcher(msg, recvbyte); } void ProtocolGame::parsePacketDead(uint8_t recvbyte) { @@ -930,7 +925,7 @@ void ProtocolGame::parsePacketDead(uint8_t recvbyte) { g_game().removePlayerUniqueLogin(player->getName()); } disconnect(); - g_dispatcher().addEvent(std::bind(&IOLoginData::updateOnlineStatus, player->getGUID(), false), "IOLoginData::updateOnlineStatus"); + IOLoginData::updateOnlineStatus(player->getGUID(), false); return; } @@ -939,23 +934,27 @@ void ProtocolGame::parsePacketDead(uint8_t recvbyte) { return; } - g_dispatcher().scheduleEvent(100, std::bind(&ProtocolGame::sendPing, getThis()), "ProtocolGame::sendPing"); + g_dispatcher().scheduleEvent( + 100, [self = getThis()] { self->sendPing(); }, "ProtocolGame::sendPing" + ); if (!player->spawn()) { disconnect(); - addGameTask(&Game::removeCreature, player, true); + g_game().removeCreature(player, true); return; } - g_dispatcher().addEvent(std::bind(&ProtocolGame::sendAddCreature, getThis(), player, player->getPosition(), 0, false), "ProtocolGame::sendAddCreature"); - g_dispatcher().addEvent(std::bind(&ProtocolGame::addBless, getThis()), "ProtocolGame::addBless"); + sendAddCreature(player, player->getPosition(), 0, false); + addBless(); resetPlayerDeathTime(); return; } if (recvbyte == 0x1D) { // keep the connection alive - g_dispatcher().scheduleEvent(100, std::bind(&ProtocolGame::sendPingBack, getThis()), "ProtocolGame::sendPingBack"); + g_dispatcher().scheduleEvent( + 100, [self = getThis()] { self->sendPingBack(); }, "ProtocolGame::sendPingBack" + ); return; } } @@ -978,13 +977,13 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt switch (recvbyte) { case 0x14: - g_dispatcher().addEvent(std::bind(&ProtocolGame::logout, getThis(), true, false), "ProtocolGame::logout"); + logout(true, false); break; case 0x1D: - addGameTask(&Game::playerReceivePingBack, player->getID()); + g_game().playerReceivePingBack(player->getID()); break; case 0x1E: - addGameTask(&Game::playerReceivePing, player->getID()); + g_game().playerReceivePing(player->getID()); break; case 0x2a: parseCyclopediaMonsterTracker(msg); @@ -1020,43 +1019,43 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parseAutoWalk(msg); break; case 0x65: - addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTH); + g_game().playerMove(player->getID(), DIRECTION_NORTH); break; case 0x66: - addGameTask(&Game::playerMove, player->getID(), DIRECTION_EAST); + g_game().playerMove(player->getID(), DIRECTION_EAST); break; case 0x67: - addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTH); + g_game().playerMove(player->getID(), DIRECTION_SOUTH); break; case 0x68: - addGameTask(&Game::playerMove, player->getID(), DIRECTION_WEST); + g_game().playerMove(player->getID(), DIRECTION_WEST); break; case 0x69: - addGameTask(&Game::playerStopAutoWalk, player->getID()); + g_game().playerStopAutoWalk(player->getID()); break; case 0x6A: - addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTHEAST); + g_game().playerMove(player->getID(), DIRECTION_NORTHEAST); break; case 0x6B: - addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTHEAST); + g_game().playerMove(player->getID(), DIRECTION_SOUTHEAST); break; case 0x6C: - addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTHWEST); + g_game().playerMove(player->getID(), DIRECTION_SOUTHWEST); break; case 0x6D: - addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTHWEST); + g_game().playerMove(player->getID(), DIRECTION_NORTHWEST); break; case 0x6F: - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerTurn", &Game::playerTurn, player->getID(), DIRECTION_NORTH); + g_game().playerTurn(player->getID(), DIRECTION_NORTH); break; case 0x70: - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerTurn", &Game::playerTurn, player->getID(), DIRECTION_EAST); + g_game().playerTurn(player->getID(), DIRECTION_EAST); break; case 0x71: - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerTurn", &Game::playerTurn, player->getID(), DIRECTION_SOUTH); + g_game().playerTurn(player->getID(), DIRECTION_SOUTH); break; case 0x72: - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerTurn", &Game::playerTurn, player->getID(), DIRECTION_WEST); + g_game().playerTurn(player->getID(), DIRECTION_WEST); break; case 0x73: parseTeleport(msg); @@ -1077,7 +1076,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parsePlayerSellOnShop(msg); break; case 0x7C: - addGameTask(&Game::playerCloseShop, player->getID()); + g_game().playerCloseShop(player->getID()); break; case 0x7D: parseRequestTrade(msg); @@ -1086,10 +1085,10 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parseLookInTrade(msg); break; case 0x7F: - addGameTask(&Game::playerAcceptTrade, player->getID()); + g_game().playerAcceptTrade(player->getID()); break; case 0x80: - addGameTask(&Game::playerCloseTrade, player->getID()); + g_game().playerCloseTrade(player->getID()); break; case 0x82: parseUseItem(msg); @@ -1154,7 +1153,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parseSay(msg); break; case 0x97: - addGameTask(&Game::playerRequestChannels, player->getID()); + g_game().playerRequestChannels(player->getID()); break; case 0x98: parseOpenChannel(msg); @@ -1166,7 +1165,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parseOpenPrivateChannel(msg); break; case 0x9E: - addGameTask(&Game::playerCloseNpcChannel, player->getID()); + g_game().playerCloseNpcChannel(player->getID()); break; case 0x9F: parseSetMonsterPodium(msg); @@ -1193,13 +1192,13 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parsePassPartyLeadership(msg); break; case 0xA7: - addGameTask(&Game::playerLeaveParty, player->getID()); + g_game().playerLeaveParty(player->getID()); break; case 0xA8: parseEnableSharedPartyExperience(msg); break; case 0xAA: - addGameTask(&Game::playerCreatePrivateChannel, player->getID()); + g_game().playerCreatePrivateChannel(player->getID()); break; case 0xAB: parseChannelInvite(msg); @@ -1223,7 +1222,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parseTaskHuntingAction(msg); break; case 0xBE: - addGameTask(&Game::playerCancelAttackAndFollow, player->getID()); + g_game().playerCancelAttackAndFollow(player->getID()); break; case 0xBF: parseForgeEnter(msg); @@ -1246,11 +1245,10 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt parseInspectionObject(msg); break; case 0xD2: - addGameTask(&Game::playerRequestOutfit, player->getID()); + g_game().playerRequestOutfit(player->getID()); break; - // g_dispatcher().addEvent(std::bind(&Modules::executeOnRecvbyte, g_modules, player, msg, recvbyte)); case 0xD3: - g_dispatcher().addEvent(std::bind(&ProtocolGame::parseSetOutfit, getThis(), msg), "ProtocolGame::parseSetOutfit"); + parseSetOutfit(msg); break; case 0xD4: parseToggleMount(msg); @@ -1309,7 +1307,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt // Premium coins transfer // case 0xEF: parseCoinTransfer(msg); break; case 0xF0: - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerShowQuestLog", &Game::playerShowQuestLog, player->getID()); + g_game().playerShowQuestLog(player->getID()); break; case 0xF1: parseQuestLine(msg); @@ -1360,7 +1358,7 @@ void ProtocolGame::parseHotkeyEquip(NetworkMessage &msg) { uint16_t itemId = msg.get(); uint8_t tier = msg.get(); - addGameTask(&Game::playerEquipItem, player->getID(), itemId, Item::items[itemId].upgradeClassification > 0, tier); + g_game().playerEquipItem(player->getID(), itemId, Item::items[itemId].upgradeClassification > 0, tier); } void ProtocolGame::GetTileDescription(std::shared_ptr tile, NetworkMessage &msg) { @@ -1563,27 +1561,27 @@ bool ProtocolGame::canSee(int32_t x, int32_t y, int32_t z) const { // Parse methods void ProtocolGame::parseChannelInvite(NetworkMessage &msg) { const std::string name = msg.getString(); - addGameTask(&Game::playerChannelInvite, player->getID(), name); + g_game().playerChannelInvite(player->getID(), name); } void ProtocolGame::parseChannelExclude(NetworkMessage &msg) { const std::string name = msg.getString(); - addGameTask(&Game::playerChannelExclude, player->getID(), name); + g_game().playerChannelExclude(player->getID(), name); } void ProtocolGame::parseOpenChannel(NetworkMessage &msg) { uint16_t channelId = msg.get(); - addGameTask(&Game::playerOpenChannel, player->getID(), channelId); + g_game().playerOpenChannel(player->getID(), channelId); } void ProtocolGame::parseCloseChannel(NetworkMessage &msg) { uint16_t channelId = msg.get(); - addGameTask(&Game::playerCloseChannel, player->getID(), channelId); + g_game().playerCloseChannel(player->getID(), channelId); } void ProtocolGame::parseOpenPrivateChannel(NetworkMessage &msg) { - const std::string receiver = msg.getString(); - addGameTask(&Game::playerOpenPrivateChannel, player->getID(), receiver); + std::string receiver = msg.getString(); + g_game().playerOpenPrivateChannel(player->getID(), receiver); } void ProtocolGame::parseAutoWalk(NetworkMessage &msg) { @@ -1631,7 +1629,7 @@ void ProtocolGame::parseAutoWalk(NetworkMessage &msg) { return; } - addGameTask(&Game::playerAutoWalk, player->getID(), path.data()); + g_game().playerAutoWalk(player->getID(), path.data()); } void ProtocolGame::parseSetOutfit(NetworkMessage &msg) { @@ -1688,23 +1686,23 @@ void ProtocolGame::parseSetOutfit(NetworkMessage &msg) { void ProtocolGame::parseToggleMount(NetworkMessage &msg) { bool mount = msg.getByte() != 0; - addGameTask(&Game::playerToggleMount, player->getID(), mount); + g_game().playerToggleMount(player->getID(), mount); } void ProtocolGame::parseApplyImbuement(NetworkMessage &msg) { uint8_t slot = msg.getByte(); uint32_t imbuementId = msg.get(); bool protectionCharm = msg.getByte() != 0x00; - addGameTask(&Game::playerApplyImbuement, player->getID(), imbuementId, slot, protectionCharm); + g_game().playerApplyImbuement(player->getID(), imbuementId, slot, protectionCharm); } void ProtocolGame::parseClearImbuement(NetworkMessage &msg) { uint8_t slot = msg.getByte(); - addGameTask(&Game::playerClearImbuement, player->getID(), slot); + g_game().playerClearImbuement(player->getID(), slot); } void ProtocolGame::parseCloseImbuementWindow(NetworkMessage &) { - addGameTask(&Game::playerCloseImbuementWindow, player->getID()); + g_game().playerCloseImbuementWindow(player->getID()); } void ProtocolGame::parseUseItem(NetworkMessage &msg) { @@ -1712,7 +1710,7 @@ void ProtocolGame::parseUseItem(NetworkMessage &msg) { uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); uint8_t index = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerUseItem", &Game::playerUseItem, player->getID(), pos, stackpos, index, itemId); + g_game().playerUseItem(player->getID(), pos, stackpos, index, itemId); } void ProtocolGame::parseUseItemEx(NetworkMessage &msg) { @@ -1722,7 +1720,7 @@ void ProtocolGame::parseUseItemEx(NetworkMessage &msg) { Position toPos = msg.getPosition(); uint16_t toItemId = msg.get(); uint8_t toStackPos = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerUseItemEx", &Game::playerUseItemEx, player->getID(), fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId); + g_game().playerUseItemEx(player->getID(), fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId); } void ProtocolGame::parseUseWithCreature(NetworkMessage &msg) { @@ -1730,27 +1728,27 @@ void ProtocolGame::parseUseWithCreature(NetworkMessage &msg) { uint16_t itemId = msg.get(); uint8_t fromStackPos = msg.getByte(); uint32_t creatureId = msg.get(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerUseWithCreature", &Game::playerUseWithCreature, player->getID(), fromPos, fromStackPos, creatureId, itemId); + g_game().playerUseWithCreature(player->getID(), fromPos, fromStackPos, creatureId, itemId); } void ProtocolGame::parseCloseContainer(NetworkMessage &msg) { uint8_t cid = msg.getByte(); - addGameTask(&Game::playerCloseContainer, player->getID(), cid); + g_game().playerCloseContainer(player->getID(), cid); } void ProtocolGame::parseUpArrowContainer(NetworkMessage &msg) { uint8_t cid = msg.getByte(); - addGameTask(&Game::playerMoveUpContainer, player->getID(), cid); + g_game().playerMoveUpContainer(player->getID(), cid); } void ProtocolGame::parseUpdateContainer(NetworkMessage &msg) { uint8_t cid = msg.getByte(); - addGameTask(&Game::playerUpdateContainer, player->getID(), cid); + g_game().playerUpdateContainer(player->getID(), cid); } void ProtocolGame::parseTeleport(NetworkMessage &msg) { Position newPosition = msg.getPosition(); - addGameTask(&Game::playerTeleport, player->getID(), newPosition); + g_game().playerTeleport(player->getID(), newPosition); } void ProtocolGame::parseThrow(NetworkMessage &msg) { @@ -1761,7 +1759,7 @@ void ProtocolGame::parseThrow(NetworkMessage &msg) { uint8_t count = msg.getByte(); if (toPos != fromPos) { - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerMoveThing", &Game::playerMoveThing, player->getID(), fromPos, itemId, fromStackpos, toPos, count); + g_game().playerMoveThing(player->getID(), fromPos, itemId, fromStackpos, toPos, count); } } @@ -1769,12 +1767,12 @@ void ProtocolGame::parseLookAt(NetworkMessage &msg) { Position pos = msg.getPosition(); uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerLookAt", &Game::playerLookAt, player->getID(), itemId, pos, stackpos); + g_game().playerLookAt(player->getID(), itemId, pos, stackpos); } void ProtocolGame::parseLookInBattleList(NetworkMessage &msg) { uint32_t creatureId = msg.get(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerLookInBattleList", &Game::playerLookInBattleList, player->getID(), creatureId); + g_game().playerLookInBattleList(player->getID(), creatureId); } void ProtocolGame::parseQuickLoot(NetworkMessage &msg) { @@ -1787,7 +1785,7 @@ void ProtocolGame::parseQuickLoot(NetworkMessage &msg) { uint8_t stackpos = msg.getByte(); bool lootAllCorpses = msg.getByte(); bool autoLoot = msg.getByte(); - addGameTask(&Game::playerQuickLoot, player->getID(), pos, itemId, stackpos, nullptr, lootAllCorpses, autoLoot); + g_game().playerQuickLoot(player->getID(), pos, itemId, stackpos, nullptr, lootAllCorpses, autoLoot); } void ProtocolGame::parseLootContainer(NetworkMessage &msg) { @@ -1801,29 +1799,29 @@ void ProtocolGame::parseLootContainer(NetworkMessage &msg) { Position pos = msg.getPosition(); uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); - addGameTask(&Game::playerSetManagedContainer, player->getID(), category, pos, itemId, stackpos, true); + g_game().playerSetManagedContainer(player->getID(), category, pos, itemId, stackpos, true); } else if (action == 1) { ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); - addGameTask(&Game::playerClearManagedContainer, player->getID(), category, true); + g_game().playerClearManagedContainer(player->getID(), category, true); } else if (action == 2) { ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); - addGameTask(&Game::playerOpenManagedContainer, player->getID(), category, true); + g_game().playerOpenManagedContainer(player->getID(), category, true); } else if (action == 3) { bool useMainAsFallback = msg.getByte() == 1; - addGameTask(&Game::playerSetQuickLootFallback, player->getID(), useMainAsFallback); + g_game().playerSetQuickLootFallback(player->getID(), useMainAsFallback); } else if (action == 4) { ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); Position pos = msg.getPosition(); uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); g_logger().debug("[{}] action {}, category {}, pos {}, itemId {}, stackPos {}", __FUNCTION__, action, static_cast(category), pos.toString(), itemId, stackpos); - addGameTask(&Game::playerSetManagedContainer, player->getID(), category, pos, itemId, stackpos, false); + g_game().playerSetManagedContainer(player->getID(), category, pos, itemId, stackpos, false); } else if (action == 5) { ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); - addGameTask(&Game::playerClearManagedContainer, player->getID(), category, false); + g_game().playerClearManagedContainer(player->getID(), category, false); } else if (action == 6) { ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); - addGameTask(&Game::playerOpenManagedContainer, player->getID(), category, false); + g_game().playerOpenManagedContainer(player->getID(), category, false); } g_logger().debug("[{}] action type {}", __FUNCTION__, action); @@ -1844,7 +1842,7 @@ void ProtocolGame::parseQuickLootBlackWhitelist(NetworkMessage &msg) { listedItems.push_back(msg.get()); } - addGameTask(&Game::playerQuickLootBlackWhitelist, player->getID(), filter, listedItems); + g_game().playerQuickLootBlackWhitelist(player->getID(), filter, listedItems); } void ProtocolGame::parseSay(NetworkMessage &msg) { @@ -1874,7 +1872,7 @@ void ProtocolGame::parseSay(NetworkMessage &msg) { return; } - addGameTask(&Game::playerSay, player->getID(), channelId, type, receiver, text); + g_game().playerSay(player->getID(), channelId, type, receiver, text); } void ProtocolGame::parseFightModes(NetworkMessage &msg) { @@ -1892,38 +1890,38 @@ void ProtocolGame::parseFightModes(NetworkMessage &msg) { fightMode = FIGHTMODE_DEFENSE; } - addGameTask(&Game::playerSetFightModes, player->getID(), fightMode, rawChaseMode != 0, rawSecureMode != 0); + g_game().playerSetFightModes(player->getID(), fightMode, rawChaseMode != 0, rawSecureMode != 0); } void ProtocolGame::parseAttack(NetworkMessage &msg) { uint32_t creatureId = msg.get(); // msg.get(); creatureId (same as above) - addGameTask(&Game::playerSetAttackedCreature, player->getID(), creatureId); + g_game().playerSetAttackedCreature(player->getID(), creatureId); } void ProtocolGame::parseFollow(NetworkMessage &msg) { uint32_t creatureId = msg.get(); // msg.get(); creatureId (same as above) - addGameTask(&Game::playerFollowCreature, player->getID(), creatureId); + g_game().playerFollowCreature(player->getID(), creatureId); } void ProtocolGame::parseTextWindow(NetworkMessage &msg) { uint32_t windowTextId = msg.get(); const std::string newText = msg.getString(); - addGameTask(&Game::playerWriteItem, player->getID(), windowTextId, newText); + g_game().playerWriteItem(player->getID(), windowTextId, newText); } void ProtocolGame::parseHouseWindow(NetworkMessage &msg) { uint8_t doorId = msg.getByte(); uint32_t id = msg.get(); const std::string text = msg.getString(); - addGameTask(&Game::playerUpdateHouseWindow, player->getID(), doorId, id, text); + g_game().playerUpdateHouseWindow(player->getID(), doorId, id, text); } void ProtocolGame::parseLookInShop(NetworkMessage &msg) { uint16_t id = msg.get(); uint8_t count = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerLookInShop", &Game::playerLookInShop, player->getID(), id, count); + g_game().playerLookInShop(player->getID(), id, count); } void ProtocolGame::parsePlayerBuyOnShop(NetworkMessage &msg) { @@ -1932,7 +1930,7 @@ void ProtocolGame::parsePlayerBuyOnShop(NetworkMessage &msg) { uint16_t amount = oldProtocol ? static_cast(msg.getByte()) : msg.get(); bool ignoreCap = msg.getByte() != 0; bool inBackpacks = msg.getByte() != 0; - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerBuyItem", &Game::playerBuyItem, player->getID(), id, count, amount, ignoreCap, inBackpacks); + g_game().playerBuyItem(player->getID(), id, count, amount, ignoreCap, inBackpacks); } void ProtocolGame::parsePlayerSellOnShop(NetworkMessage &msg) { @@ -1941,7 +1939,7 @@ void ProtocolGame::parsePlayerSellOnShop(NetworkMessage &msg) { uint16_t amount = oldProtocol ? static_cast(msg.getByte()) : msg.get(); bool ignoreEquipped = msg.getByte() != 0; - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerSellItem", &Game::playerSellItem, player->getID(), id, count, amount, ignoreEquipped); + g_game().playerSellItem(player->getID(), id, count, amount, ignoreEquipped); } void ProtocolGame::parseRequestTrade(NetworkMessage &msg) { @@ -1949,23 +1947,23 @@ void ProtocolGame::parseRequestTrade(NetworkMessage &msg) { uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); uint32_t playerId = msg.get(); - addGameTask(&Game::playerRequestTrade, player->getID(), pos, stackpos, playerId, itemId); + g_game().playerRequestTrade(player->getID(), pos, stackpos, playerId, itemId); } void ProtocolGame::parseLookInTrade(NetworkMessage &msg) { bool counterOffer = (msg.getByte() == 0x01); uint8_t index = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerLookInTrade", &Game::playerLookInTrade, player->getID(), counterOffer, index); + g_game().playerLookInTrade(player->getID(), counterOffer, index); } void ProtocolGame::parseAddVip(NetworkMessage &msg) { const std::string name = msg.getString(); - addGameTask(&Game::playerRequestAddVip, player->getID(), name); + g_game().playerRequestAddVip(player->getID(), name); } void ProtocolGame::parseRemoveVip(NetworkMessage &msg) { uint32_t guid = msg.get(); - addGameTask(&Game::playerRequestRemoveVip, player->getID(), guid); + g_game().playerRequestRemoveVip(player->getID(), guid); } void ProtocolGame::parseEditVip(NetworkMessage &msg) { @@ -1973,7 +1971,7 @@ void ProtocolGame::parseEditVip(NetworkMessage &msg) { const std::string description = msg.getString(); uint32_t icon = std::min(10, msg.get()); // 10 is max icon in 9.63 bool notify = msg.getByte() != 0; - addGameTask(&Game::playerRequestEditVip, player->getID(), guid, description, icon, notify); + g_game().playerRequestEditVip(player->getID(), guid, description, icon, notify); } void ProtocolGame::parseRotateItem(NetworkMessage &msg) { @@ -1982,9 +1980,9 @@ void ProtocolGame::parseRotateItem(NetworkMessage &msg) { uint8_t stackpos = msg.getByte(); const auto &itemType = Item::items[itemId]; if (itemType.isPodium) { - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerRotatePodium", &Game::playerRotatePodium, player->getID(), pos, stackpos, itemId); + g_game().playerRotatePodium(player->getID(), pos, stackpos, itemId); } else { - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerRotateItem", &Game::playerRotateItem, player->getID(), pos, stackpos, itemId); + g_game().playerRotateItem(player->getID(), pos, stackpos, itemId); } } @@ -1992,7 +1990,7 @@ void ProtocolGame::parseWrapableItem(NetworkMessage &msg) { Position pos = msg.getPosition(); uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerWrapableItem", &Game::playerWrapableItem, player->getID(), pos, stackpos, itemId); + g_game().playerWrapableItem(player->getID(), pos, stackpos, itemId); } void ProtocolGame::parseInspectionObject(NetworkMessage &msg) { @@ -2106,7 +2104,7 @@ void ProtocolGame::parseTaskHuntingAction(NetworkMessage &msg) { return; } - addGameTask(&Game::playerTaskHuntingAction, player->getID(), slot, action, upgrade, raceId); + g_game().playerTaskHuntingAction(player->getID(), slot, action, upgrade, raceId); } void ProtocolGame::sendHighscoresNoData() { @@ -2220,7 +2218,7 @@ void ProtocolGame::parseRuleViolationReport(NetworkMessage &msg) { msg.get(); // statement id, used to get whatever player have said, we don't log that. } - addGameTask(&Game::playerReportRuleViolationReport, player->getID(), targetName, reportType, reportReason, comment, translation); + g_game().playerReportRuleViolationReport(player->getID(), targetName, reportType, reportReason, comment, translation); } void ProtocolGame::parseBestiarysendRaces() { @@ -2942,12 +2940,12 @@ void ProtocolGame::parseBugReport(NetworkMessage &msg) { position = msg.getPosition(); } - addGameTask(&Game::playerReportBug, player->getID(), message, position, category); + g_game().playerReportBug(player->getID(), message, position, category); } void ProtocolGame::parseGreet(NetworkMessage &msg) { uint32_t npcId = msg.get(); - addGameTask(&Game::playerNpcGreet, player->getID(), npcId); + g_game().playerNpcGreet(player->getID(), npcId); } void ProtocolGame::parseDebugAssert(NetworkMessage &msg) { @@ -2961,7 +2959,7 @@ void ProtocolGame::parseDebugAssert(NetworkMessage &msg) { std::string date = msg.getString(); std::string description = msg.getString(); std::string comment = msg.getString(); - addGameTask(&Game::playerDebugAssert, player->getID(), assertLine, date, description, comment); + g_game().playerDebugAssert(player->getID(), assertLine, date, description, comment); } void ProtocolGame::parsePreyAction(NetworkMessage &msg) { @@ -2982,7 +2980,7 @@ void ProtocolGame::parsePreyAction(NetworkMessage &msg) { return; } - addGameTask(&Game::playerPreyAction, player->getID(), slot, action, option, index, raceId); + g_game().playerPreyAction(player->getID(), slot, action, option, index, raceId); } void ProtocolGame::parseSendResourceBalance() { @@ -3001,52 +2999,52 @@ void ProtocolGame::parseSendResourceBalance() { void ProtocolGame::parseInviteToParty(NetworkMessage &msg) { uint32_t targetId = msg.get(); - addGameTask(&Game::playerInviteToParty, player->getID(), targetId); + g_game().playerInviteToParty(player->getID(), targetId); } void ProtocolGame::parseJoinParty(NetworkMessage &msg) { uint32_t targetId = msg.get(); - addGameTask(&Game::playerJoinParty, player->getID(), targetId); + g_game().playerJoinParty(player->getID(), targetId); } void ProtocolGame::parseRevokePartyInvite(NetworkMessage &msg) { uint32_t targetId = msg.get(); - addGameTask(&Game::playerRevokePartyInvitation, player->getID(), targetId); + g_game().playerRevokePartyInvitation(player->getID(), targetId); } void ProtocolGame::parsePassPartyLeadership(NetworkMessage &msg) { uint32_t targetId = msg.get(); - addGameTask(&Game::playerPassPartyLeadership, player->getID(), targetId); + g_game().playerPassPartyLeadership(player->getID(), targetId); } void ProtocolGame::parseEnableSharedPartyExperience(NetworkMessage &msg) { bool sharedExpActive = msg.getByte() == 1; - addGameTask(&Game::playerEnableSharedPartyExperience, player->getID(), sharedExpActive); + g_game().playerEnableSharedPartyExperience(player->getID(), sharedExpActive); } void ProtocolGame::parseQuestLine(NetworkMessage &msg) { uint16_t questId = msg.get(); - addGameTask(&Game::playerShowQuestLine, player->getID(), questId); + g_game().playerShowQuestLine(player->getID(), questId); } void ProtocolGame::parseMarketLeave() { - addGameTask(&Game::playerLeaveMarket, player->getID()); + g_game().playerLeaveMarket(player->getID()); } void ProtocolGame::parseMarketBrowse(NetworkMessage &msg) { uint16_t browseId = oldProtocol ? msg.get() : static_cast(msg.getByte()); if ((oldProtocol && browseId == MARKETREQUEST_OWN_OFFERS_OLD) || (!oldProtocol && browseId == MARKETREQUEST_OWN_OFFERS)) { - addGameTask(&Game::playerBrowseMarketOwnOffers, player->getID()); + g_game().playerBrowseMarketOwnOffers(player->getID()); } else if ((oldProtocol && browseId == MARKETREQUEST_OWN_HISTORY_OLD) || (!oldProtocol && browseId == MARKETREQUEST_OWN_HISTORY)) { - addGameTask(&Game::playerBrowseMarketOwnHistory, player->getID()); + g_game().playerBrowseMarketOwnHistory(player->getID()); } else if (!oldProtocol) { uint16_t itemId = msg.get(); uint8_t tier = msg.get(); player->sendMarketEnter(player->getLastDepotId()); - addGameTask(&Game::playerBrowseMarket, player->getID(), itemId, tier); + g_game().playerBrowseMarket(player->getID(), itemId, tier); } else { - addGameTask(&Game::playerBrowseMarket, player->getID(), browseId, 0); + g_game().playerBrowseMarket(player->getID(), browseId, 0); } } @@ -3062,7 +3060,7 @@ void ProtocolGame::parseMarketCreateOffer(NetworkMessage &msg) { uint64_t price = oldProtocol ? static_cast(msg.get()) : msg.get(); bool anonymous = (msg.getByte() != 0); if (amount > 0 && price > 0) { - addGameTask(&Game::playerCreateMarketOffer, player->getID(), type, itemId, amount, price, itemTier, anonymous); + g_game().playerCreateMarketOffer(player->getID(), type, itemId, amount, price, itemTier, anonymous); } } @@ -3070,7 +3068,7 @@ void ProtocolGame::parseMarketCancelOffer(NetworkMessage &msg) { uint32_t timestamp = msg.get(); uint16_t counter = msg.get(); if (counter > 0) { - addGameTask(&Game::playerCancelMarketOffer, player->getID(), timestamp, counter); + g_game().playerCancelMarketOffer(player->getID(), timestamp, counter); } updateCoinBalance(); @@ -3081,7 +3079,7 @@ void ProtocolGame::parseMarketAcceptOffer(NetworkMessage &msg) { uint16_t counter = msg.get(); uint16_t amount = msg.get(); if (amount > 0 && counter > 0) { - addGameTask(&Game::playerAcceptMarketOffer, player->getID(), timestamp, counter, amount); + g_game().playerAcceptMarketOffer(player->getID(), timestamp, counter, amount); } updateCoinBalance(); @@ -3091,7 +3089,7 @@ void ProtocolGame::parseModalWindowAnswer(NetworkMessage &msg) { uint32_t id = msg.get(); uint8_t button = msg.getByte(); uint8_t choice = msg.getByte(); - addGameTask(&Game::playerAnswerModalWindow, player->getID(), id, button, choice); + g_game().playerAnswerModalWindow(player->getID(), id, button, choice); } void ProtocolGame::parseRewardChestCollect(NetworkMessage &msg) { @@ -3106,19 +3104,19 @@ void ProtocolGame::parseRewardChestCollect(NetworkMessage &msg) { } auto maxCollectItems = g_configManager().getNumber(REWARD_CHEST_MAX_COLLECT_ITEMS, __FUNCTION__); - addGameTask(&Game::playerRewardChestCollect, player->getID(), position, itemId, stackPosition, maxCollectItems); + g_game().playerRewardChestCollect(player->getID(), position, itemId, stackPosition, maxCollectItems); } void ProtocolGame::parseBrowseField(NetworkMessage &msg) { const Position &pos = msg.getPosition(); - addGameTask(&Game::playerBrowseField, player->getID(), pos); + g_game().playerBrowseField(player->getID(), pos); } void ProtocolGame::parseSeekInContainer(NetworkMessage &msg) { uint8_t containerId = msg.getByte(); uint16_t index = msg.get(); auto primaryType = msg.getByte(); - addGameTask(&Game::playerSeekInContainer, player->getID(), containerId, index, primaryType); + g_game().playerSeekInContainer(player->getID(), containerId, index, primaryType); } // Send methods @@ -4660,23 +4658,18 @@ void ProtocolGame::updateCoinBalance() { return; } - g_dispatcher().addEvent( - std::bind( - [](uint32_t playerId) { - auto threadPlayer = g_game().getPlayerByID(playerId); - if (threadPlayer && threadPlayer->getAccount()) { - auto [coins, errCoin] = threadPlayer->getAccount()->getCoins(enumToValue(CoinType::Normal)); - auto [transferCoins, errTCoin] = threadPlayer->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + g_dispatcher().addEvent([playerId = player->getID()] { + const auto &threadPlayer = g_game().getPlayerByID(playerId); + if (threadPlayer && threadPlayer->getAccount()) { + const auto [coins, errCoin] = threadPlayer->getAccount()->getCoins(enumToValue(CoinType::Normal)); + const auto [transferCoins, errTCoin] = threadPlayer->getAccount()->getCoins(enumToValue(CoinType::Transferable)); - threadPlayer->coinBalance = coins; - threadPlayer->coinTransferableBalance = transferCoins; - threadPlayer->sendCoinBalance(); - } - }, - player->getID() - ), - "ProtocolGame::updateCoinBalance" - ); + threadPlayer->coinBalance = coins; + threadPlayer->coinTransferableBalance = transferCoins; + threadPlayer->sendCoinBalance(); + } + }, + "ProtocolGame::updateCoinBalance"); } void ProtocolGame::sendMarketLeave() { @@ -5224,11 +5217,11 @@ void ProtocolGame::parseForgeEnter(NetworkMessage &msg) { bool usedCore = msg.getByte(); bool reduceTierLoss = msg.getByte(); if (actionType == ForgeAction_t::FUSION) { - addGameTask(&Game::playerForgeFuseItems, player->getID(), actionType, firstItem, tier, secondItem, usedCore, reduceTierLoss, convergence); + g_game().playerForgeFuseItems(player->getID(), actionType, firstItem, tier, secondItem, usedCore, reduceTierLoss, convergence); } else if (actionType == ForgeAction_t::TRANSFER) { - addGameTask(&Game::playerForgeTransferItemTier, player->getID(), actionType, firstItem, tier, secondItem, convergence); + g_game().playerForgeTransferItemTier(player->getID(), actionType, firstItem, tier, secondItem, convergence); } else if (actionType <= ForgeAction_t::INCREASELIMIT) { - addGameTask(&Game::playerForgeResourceConversion, player->getID(), actionType); + g_game().playerForgeResourceConversion(player->getID(), actionType); } } @@ -5237,7 +5230,7 @@ void ProtocolGame::parseForgeBrowseHistory(NetworkMessage &msg) { return; } - addGameTask(&Game::playerBrowseForgeHistory, player->getID(), msg.getByte()); + g_game().playerBrowseForgeHistory(player->getID(), msg.getByte()); } void ProtocolGame::sendForgeResult(ForgeAction_t actionType, uint16_t leftItemId, uint8_t leftTier, uint16_t rightItemId, uint8_t rightTier, bool success, uint8_t bonus, uint8_t coreCount, bool convergence) { @@ -7884,7 +7877,7 @@ void ProtocolGame::parseExtendedOpcode(NetworkMessage &msg) { const std::string &buffer = msg.getString(); // process additional opcodes via lua script event - addGameTask(&Game::parsePlayerExtendedOpcode, player->getID(), opcode, buffer); + g_game().parsePlayerExtendedOpcode(player->getID(), opcode, buffer); } // OTCv8 @@ -7917,7 +7910,7 @@ void ProtocolGame::parseInventoryImbuements(NetworkMessage &msg) { } bool isTrackerOpen = msg.getByte(); // Window is opened or closed - addGameTask(&Game::playerRequestInventoryImbuements, player->getID(), isTrackerOpen); + g_game().playerRequestInventoryImbuements(player->getID(), isTrackerOpen); } void ProtocolGame::sendInventoryImbuements(const std::map> items) { @@ -8082,28 +8075,28 @@ void ProtocolGame::parseStashWithdraw(NetworkMessage &msg) { uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); uint32_t count = msg.getByte(); - addGameTask(&Game::playerStowItem, player->getID(), pos, itemId, stackpos, count, false); + g_game().playerStowItem(player->getID(), pos, itemId, stackpos, count, false); break; } case SUPPLY_STASH_ACTION_STOW_CONTAINER: { Position pos = msg.getPosition(); uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); - addGameTask(&Game::playerStowItem, player->getID(), pos, itemId, stackpos, 0, false); + g_game().playerStowItem(player->getID(), pos, itemId, stackpos, 0, false); break; } case SUPPLY_STASH_ACTION_STOW_STACK: { Position pos = msg.getPosition(); uint16_t itemId = msg.get(); uint8_t stackpos = msg.getByte(); - addGameTask(&Game::playerStowItem, player->getID(), pos, itemId, stackpos, 0, true); + g_game().playerStowItem(player->getID(), pos, itemId, stackpos, 0, true); break; } case SUPPLY_STASH_ACTION_WITHDRAW: { uint16_t itemId = msg.get(); uint32_t count = msg.get(); uint8_t stackpos = msg.getByte(); - addGameTask(&Game::playerStashWithdraw, player->getID(), itemId, count, stackpos); + g_game().playerStashWithdraw(player->getID(), itemId, count, stackpos); break; } default: @@ -8196,7 +8189,7 @@ void ProtocolGame::parseOpenDepotSearch() { return; } - addGameTask(&Game::playerRequestDepotItems, player->getID()); + g_game().playerRequestDepotItems(player->getID()); } void ProtocolGame::parseCloseDepotSearch() { @@ -8204,7 +8197,7 @@ void ProtocolGame::parseCloseDepotSearch() { return; } - addGameTask(&Game::playerRequestCloseDepotSearch, player->getID()); + g_game().playerRequestCloseDepotSearch(player->getID()); } void ProtocolGame::parseDepotSearchItemRequest(NetworkMessage &msg) { @@ -8218,7 +8211,7 @@ void ProtocolGame::parseDepotSearchItemRequest(NetworkMessage &msg) { itemTier = msg.getByte(); } - addGameTask(&Game::playerRequestDepotSearchItem, player->getID(), itemId, itemTier); + g_game().playerRequestDepotSearchItem(player->getID(), itemId, itemTier); } void ProtocolGame::parseRetrieveDepotSearch(NetworkMessage &msg) { @@ -8233,7 +8226,7 @@ void ProtocolGame::parseRetrieveDepotSearch(NetworkMessage &msg) { } uint8_t type = msg.getByte(); - addGameTask(&Game::playerRequestDepotSearchRetrieve, player->getID(), itemId, itemTier, type); + g_game().playerRequestDepotSearchRetrieve(player->getID(), itemId, itemTier, type); } void ProtocolGame::parseOpenParentContainer(NetworkMessage &msg) { @@ -8242,7 +8235,7 @@ void ProtocolGame::parseOpenParentContainer(NetworkMessage &msg) { } Position pos = msg.getPosition(); - addGameTask(&Game::playerRequestOpenContainerFromDepotSearch, player->getID(), pos); + g_game().playerRequestOpenContainerFromDepotSearch(player->getID(), pos); } void ProtocolGame::sendUpdateCreature(std::shared_ptr creature) { @@ -8530,7 +8523,7 @@ void ProtocolGame::parseBosstiarySlot(NetworkMessage &msg) { uint8_t slotBossId = msg.getByte(); uint32_t selectedBossId = msg.get(); - addGameTask(&Game::playerBosstiarySlot, player->getID(), slotBossId, selectedBossId); + g_game().playerBosstiarySlot(player->getID(), slotBossId, selectedBossId); } void ProtocolGame::sendPodiumDetails(NetworkMessage &msg, const std::vector &toSendMonsters, bool isBoss) const { @@ -8745,7 +8738,7 @@ void ProtocolGame::parseOpenWheel(NetworkMessage &msg) { } auto ownerId = msg.get(); - addGameTask(&Game::playerOpenWheel, player->getID(), ownerId); + g_game().playerOpenWheel(player->getID(), ownerId); } void ProtocolGame::parseWheelGemAction(NetworkMessage &msg) { @@ -8753,7 +8746,7 @@ void ProtocolGame::parseWheelGemAction(NetworkMessage &msg) { return; } - addGameTask(&Game::playerWheelGemAction, player->getID(), msg); + g_game().playerWheelGemAction(player->getID(), msg); } void ProtocolGame::sendOpenWheelWindow(uint32_t ownerId) { @@ -8771,7 +8764,7 @@ void ProtocolGame::parseSaveWheel(NetworkMessage &msg) { return; } - addGameTask(&Game::playerSaveWheel, player->getID(), msg); + g_game().playerSaveWheel(player->getID(), msg); } void ProtocolGame::sendDisableLoginMusic() { diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index 61c3aa19af0..306bb873f25 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -73,12 +73,6 @@ class ProtocolGame final : public Protocol { } private: - // Helpers so we don't need to bind every time - template - void addGameTask(Callable function, Args &&... args); - template - void addGameTaskTimed(uint32_t delay, std::string_view context, Callable function, Args &&... args); - ProtocolGame_ptr getThis() { return std::static_pointer_cast(shared_from_this()); } diff --git a/src/server/network/protocol/protocollogin.cpp b/src/server/network/protocol/protocollogin.cpp index 4e38a7503c7..b59a3704429 100644 --- a/src/server/network/protocol/protocollogin.cpp +++ b/src/server/network/protocol/protocollogin.cpp @@ -174,6 +174,8 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage &msg) { return; } - auto thisPtr = std::static_pointer_cast(shared_from_this()); - g_dispatcher().addEvent(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountDescriptor, password), "ProtocolLogin::getCharacterList"); + g_dispatcher().addEvent([self = std::static_pointer_cast(shared_from_this()), accountDescriptor, password] { + self->getCharacterList(accountDescriptor, password); + }, + "ProtocolLogin::getCharacterList"); } diff --git a/src/server/network/protocol/protocolstatus.cpp b/src/server/network/protocol/protocolstatus.cpp index 8d9f245f5df..a4dfe1651d6 100644 --- a/src/server/network/protocol/protocolstatus.cpp +++ b/src/server/network/protocol/protocolstatus.cpp @@ -44,7 +44,10 @@ void ProtocolStatus::onRecvFirstMessage(NetworkMessage &msg) { // XML info protocol case 0xFF: { if (msg.getString(4) == "info") { - g_dispatcher().addEvent(std::bind(&ProtocolStatus::sendStatusString, std::static_pointer_cast(shared_from_this())), "ProtocolStatus::sendStatusString"); + g_dispatcher().addEvent([self = std::static_pointer_cast(shared_from_this())] { + self->sendStatusString(); + }, + "ProtocolStatus::sendStatusString"); return; } break; @@ -57,7 +60,11 @@ void ProtocolStatus::onRecvFirstMessage(NetworkMessage &msg) { if (requestedInfo & REQUEST_PLAYER_STATUS_INFO) { characterName = msg.getString(); } - g_dispatcher().addEvent(std::bind(&ProtocolStatus::sendInfo, std::static_pointer_cast(shared_from_this()), requestedInfo, characterName), "ProtocolStatus::sendInfo"); + g_dispatcher().addEvent([self = std::static_pointer_cast(shared_from_this()), requestedInfo, characterName] { + self->sendInfo(requestedInfo, characterName); + }, + "ProtocolStatus::sendInfo"); + return; } diff --git a/src/server/server.cpp b/src/server/server.cpp index 2968033bafa..fc8690468fe 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -47,7 +47,7 @@ void ServiceManager::stop() { for (auto &servicePortIt : acceptors) { try { - io_service.post(std::bind_front(&ServicePort::onStopServer, servicePortIt.second)); + io_service.post([servicePort = servicePortIt.second] { servicePort->onStopServer(); }); } catch (const std::system_error &e) { g_logger().warn("[ServiceManager::stop] - Network error: {}", e.what()); } @@ -56,7 +56,9 @@ void ServiceManager::stop() { acceptors.clear(); death_timer.expires_from_now(std::chrono::seconds(3)); - death_timer.async_wait(std::bind(&ServiceManager::die, this)); + death_timer.async_wait([this](const std::error_code &err) { + die(); + }); } ServicePort::~ServicePort() { @@ -87,7 +89,7 @@ void ServicePort::accept() { } auto connection = ConnectionManager::getInstance().createConnection(io_service, shared_from_this()); - acceptor->async_accept(connection->getSocket(), std::bind(&ServicePort::onAccept, shared_from_this(), connection, std::placeholders::_1)); + acceptor->async_accept(connection->getSocket(), [self = shared_from_this(), connection](const std::error_code &error) { self->onAccept(connection, error); }); } void ServicePort::onAccept(Connection_ptr connection, const std::error_code &error) { @@ -113,7 +115,9 @@ void ServicePort::onAccept(Connection_ptr connection, const std::error_code &err if (!pendingStart) { close(); pendingStart = true; - g_dispatcher().scheduleEvent(15000, std::bind_front(&ServicePort::openAcceptor, std::weak_ptr(shared_from_this()), serverPort), "ServicePort::openAcceptor"); + g_dispatcher().scheduleEvent( + 15000, [self = shared_from_this(), serverPort = serverPort] { ServicePort::openAcceptor(std::weak_ptr(self), serverPort); }, "ServicePort::openAcceptor" + ); } } } @@ -162,7 +166,10 @@ void ServicePort::open(uint16_t port) { g_logger().warn("[ServicePort::open] - Error code: {}", e.what()); pendingStart = true; - g_dispatcher().scheduleEvent(15000, std::bind_front(&ServicePort::openAcceptor, std::weak_ptr(shared_from_this()), port), "ServicePort::openAcceptor"); + g_dispatcher().scheduleEvent( + 15000, + [self = shared_from_this(), port] { ServicePort::openAcceptor(std::weak_ptr(self), port); }, "ServicePort::openAcceptor" + ); } } From 5879ed5fe1c3f754ee69dad36b7fbb39f2f3d4fb Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Fri, 22 Mar 2024 18:22:29 -0300 Subject: [PATCH 02/21] fix: client update blockable spawn monsters with god (#2482) Resolves #2479 --- src/creatures/monsters/spawns/spawn_monster.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/creatures/monsters/spawns/spawn_monster.cpp b/src/creatures/monsters/spawns/spawn_monster.cpp index 5d9f386e25f..21eab1a7c0b 100644 --- a/src/creatures/monsters/spawns/spawn_monster.cpp +++ b/src/creatures/monsters/spawns/spawn_monster.cpp @@ -180,6 +180,7 @@ bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const return false; } } else { + g_logger().debug("[SpawnMonster] Spawning {} at {}", monsterType->name, sb.pos.toString()); if (!g_game().placeCreature(monster, sb.pos, false, true)) { return false; } @@ -260,7 +261,7 @@ void SpawnMonster::checkSpawnMonster() { } if (mType->info.isBlockable) { - spawnMonster(spawnMonsterId, sb, mType, true); + spawnMonster(spawnMonsterId, sb, mType); } else { scheduleSpawn(spawnMonsterId, sb, mType, 3 * NONBLOCKABLE_SPAWN_MONSTER_INTERVAL); } From ed2dbaeb1d55d49b1f7fce3c3744791d38fd232e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Lu=C3=ADs=20Lucarelo=20Lamonato?= Date: Fri, 22 Mar 2024 22:25:14 -0300 Subject: [PATCH 03/21] fix: missing function loadPlayerInstantSpellList in IOLoginData (#2483) Makes the player forget the spells he learned from NPC --- src/io/iologindata.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp index 7e113ef901e..4c6b95dc32e 100644 --- a/src/io/iologindata.cpp +++ b/src/io/iologindata.cpp @@ -172,6 +172,9 @@ bool IOLoginData::loadPlayer(std::shared_ptr player, DBResult_ptr result // Load task hunting class IOLoginDataLoad::loadPlayerTaskHuntingClass(player, result); + // Load instant spells list + IOLoginDataLoad::loadPlayerInstantSpellList(player, result); + if (disableIrrelevantInfo) { return true; } From b56395833a3eb39faf1ec3d65cb40e06a10bdc2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Lu=C3=ADs=20Lucarelo=20Lamonato?= Date: Sat, 23 Mar 2024 16:47:28 -0300 Subject: [PATCH 04/21] fix: possibility of stashing items that are far away (#2489) --- src/game/game.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index c69b481e32c..6754e990595 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1518,11 +1518,6 @@ 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; @@ -1654,7 +1649,12 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo return; } } - + + if (isTryingToStow(toPos, toCylinder)) { + player->stowItem(item, count, false); + return; + } + ReturnValue ret = internalMoveItem(fromCylinder, toCylinder, toIndex, item, count, nullptr, 0, player); if (ret != RETURNVALUE_NOERROR) { player->sendCancelMessage(ret); From 9ccfe62fdc74932149bbf3895c2022b065f34208 Mon Sep 17 00:00:00 2001 From: Beats Date: Mon, 25 Mar 2024 10:01:15 -0400 Subject: [PATCH 05/21] fix: guard all depot in stash (#2491) --- src/creatures/players/player.cpp | 8 ++++---- src/game/game.cpp | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 76ca1755c70..75e5b5ef2af 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -6452,7 +6452,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 +6463,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 +6473,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/game/game.cpp b/src/game/game.cpp index 6754e990595..11ed432da15 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1518,11 +1518,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 +1644,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); From 8dec6f96aa85bf6873c5a6598e538b7fb8853d8e Mon Sep 17 00:00:00 2001 From: Leandro Date: Mon, 25 Mar 2024 22:31:55 -0300 Subject: [PATCH 06/21] fix: auto loot reachable corpses only (#2473) --- src/creatures/creature.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) 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); }, From 9fb38cabd8e0de60fb3a22110ed5ca5535b0cecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Lu=C3=ADs=20Lucarelo=20Lamonato?= Date: Mon, 1 Apr 2024 11:50:17 -0300 Subject: [PATCH 07/21] fix: duplicated daily rewards bug (#2503) --- data/modules/scripts/daily_reward/daily_reward.lua | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/data/modules/scripts/daily_reward/daily_reward.lua b/data/modules/scripts/daily_reward/daily_reward.lua index 815a7e2611c..1f0e805704c 100644 --- a/data/modules/scripts/daily_reward/daily_reward.lua +++ b/data/modules/scripts/daily_reward/daily_reward.lua @@ -462,14 +462,12 @@ function Player.selectDailyReward(self, msg) local description = "" for k, v in ipairs(items) do if dailyTable.itemCharges then - for i = 1, rewardCount do - local inboxItem = inbox:addItem(v.itemId, dailyTable.itemCharges) -- adding charges for each item - if inboxItem then - inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) - end + local inboxItem = inbox:addItem(v.itemId, dailyTable.itemCharges) -- adding charges for each item + if inboxItem then + inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) end else - local inboxItem = inbox:addItem(v.itemId, rewardCount) -- adding single item w/o charges + local inboxItem = inbox:addItem(v.itemId, v.count) -- adding single item w/o charges if inboxItem then inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) end From 2f41230fce391fa5a7b9508b29d2e69269f9f945 Mon Sep 17 00:00:00 2001 From: Beats Date: Mon, 1 Apr 2024 11:04:38 -0400 Subject: [PATCH 08/21] improve: remove lib jsoncpp and change WildcardTreeNode to shared_ptr (#2508) --- CMakeLists.txt | 2 +- cmake/modules/BaseConfig.cmake | 1 - cmake/modules/CanaryLib.cmake | 4 +--- src/game/game.cpp | 8 +++++--- src/game/game.hpp | 2 +- src/pch.hpp | 4 +--- src/utils/wildcardtree.cpp | 26 +++++++++++++------------- src/utils/wildcardtree.hpp | 12 ++++++------ vcpkg.json | 1 - vcproj/settings.props | 2 -- 10 files changed, 28 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c8ffef6c0a..0cf201ce38f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.22 FATAL_ERROR) # VCPKG # cmake -DCMAKE_TOOLCHAIN_FILE=/opt/workspace/vcpkg/scripts/buildsystems/vcpkg.cmake .. # Needed libs is in file vcpkg.json -# Windows required libs: .\vcpkg install --triplet x64-windows asio pugixml spdlog curl jsoncpp protobuf parallel-hashmap magic-enum mio luajit libmariadb mpir abseil +# Windows required libs: .\vcpkg install --triplet x64-windows asio pugixml spdlog curl protobuf parallel-hashmap magic-enum mio luajit libmariadb mpir abseil if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") diff --git a/cmake/modules/BaseConfig.cmake b/cmake/modules/BaseConfig.cmake index 6f58a2eebdb..6a8ce69ed4b 100644 --- a/cmake/modules/BaseConfig.cmake +++ b/cmake/modules/BaseConfig.cmake @@ -31,7 +31,6 @@ find_package(ZLIB REQUIRED) find_package(absl CONFIG REQUIRED) find_package(asio CONFIG REQUIRED) find_package(eventpp CONFIG REQUIRED) -find_package(jsoncpp CONFIG REQUIRED) find_package(magic_enum CONFIG REQUIRED) find_package(opentelemetry-cpp CONFIG REQUIRED) find_package(prometheus-cpp CONFIG REQUIRED) diff --git a/cmake/modules/CanaryLib.cmake b/cmake/modules/CanaryLib.cmake index 4838935f19e..270bbf59a99 100644 --- a/cmake/modules/CanaryLib.cmake +++ b/cmake/modules/CanaryLib.cmake @@ -124,16 +124,14 @@ endif() if (MSVC) if(BUILD_STATIC_LIBRARY) - target_link_libraries(${PROJECT_NAME}_lib PUBLIC jsoncpp_static) set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "") else() - target_link_libraries(${PROJECT_NAME}_lib PUBLIC jsoncpp_lib) set(VCPKG_TARGET_TRIPLET "x64-windows" CACHE STRING "") endif() target_link_libraries(${PROJECT_NAME}_lib PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${MYSQL_CLIENT_LIBS}) else() - target_link_libraries(${PROJECT_NAME}_lib PUBLIC jsoncpp_static Threads::Threads) + target_link_libraries(${PROJECT_NAME}_lib PUBLIC Threads::Threads) endif (MSVC) # === OpenMP === diff --git a/src/game/game.cpp b/src/game/game.cpp index 11ed432da15..9310f1c9a20 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -207,6 +207,8 @@ Game::Game() { // Create instance of IOWheel to Game class m_IOWheel = std::make_unique(); + wildcardTree = std::make_shared(false); + m_highscoreCategoriesNames = { { static_cast(HighscoreCategories_t::ACHIEVEMENTS), "Achievement Points" }, { static_cast(HighscoreCategories_t::AXE_FIGHTING), "Axe Fighting" }, @@ -886,7 +888,7 @@ ReturnValue Game::getPlayerByNameWildcard(const std::string &s, std::shared_ptr< if (s.back() == '~') { const std::string &query = asLowerCaseString(s.substr(0, strlen - 1)); std::string result; - ReturnValue ret = wildcardTree.findOne(query, result); + ReturnValue ret = wildcardTree->findOne(query, result); if (ret != RETURNVALUE_NOERROR) { return ret; } @@ -9689,14 +9691,14 @@ void Game::updatePlayerSaleItems(uint32_t playerId) { void Game::addPlayer(std::shared_ptr player) { const std::string &lowercase_name = asLowerCaseString(player->getName()); mappedPlayerNames[lowercase_name] = player; - wildcardTree.insert(lowercase_name); + wildcardTree->insert(lowercase_name); players[player->getID()] = player; } void Game::removePlayer(std::shared_ptr player) { const std::string &lowercase_name = asLowerCaseString(player->getName()); mappedPlayerNames.erase(lowercase_name); - wildcardTree.remove(lowercase_name); + wildcardTree->remove(lowercase_name); players.erase(player->getID()); } diff --git a/src/game/game.hpp b/src/game/game.hpp index d70263c1775..708aa4b1782 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -840,7 +840,7 @@ class Game { size_t lastBucket = 0; size_t lastImbuedBucket = 0; - WildcardTreeNode wildcardTree { false }; + std::shared_ptr wildcardTree; std::map> npcs; std::map> monsters; diff --git a/src/pch.hpp b/src/pch.hpp index 522411b5621..7c38a99ee94 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -45,6 +45,7 @@ #include #include #include +#include // -------------------- // System Includes @@ -95,9 +96,6 @@ struct fmt::formatter, char>> : formatter< // GMP #include -// JSON -#include - // LUA #if __has_include("luajit/lua.hpp") #include diff --git a/src/utils/wildcardtree.cpp b/src/utils/wildcardtree.cpp index 1e91b9b4169..4fd830b64cb 100644 --- a/src/utils/wildcardtree.cpp +++ b/src/utils/wildcardtree.cpp @@ -11,37 +11,37 @@ #include "utils/wildcardtree.hpp" -WildcardTreeNode* WildcardTreeNode::getChild(char ch) { +std::shared_ptr WildcardTreeNode::getChild(char ch) { auto it = children.find(ch); if (it == children.end()) { return nullptr; } - return &it->second; + return it->second; } -const WildcardTreeNode* WildcardTreeNode::getChild(char ch) const { +std::shared_ptr WildcardTreeNode::getChild(char ch) const { auto it = children.find(ch); if (it == children.end()) { return nullptr; } - return &it->second; + return it->second; } -WildcardTreeNode* WildcardTreeNode::addChild(char ch, bool breakp) { - WildcardTreeNode* child = getChild(ch); +std::shared_ptr WildcardTreeNode::addChild(char ch, bool breakp) { + std::shared_ptr child = getChild(ch); if (child) { if (breakp && !child->breakpoint) { child->breakpoint = true; } } else { - auto pair = children.emplace(std::piecewise_construct, std::forward_as_tuple(ch), std::forward_as_tuple(breakp)); - child = &pair.first->second; + auto pair = children.emplace(std::piecewise_construct, std::forward_as_tuple(ch), std::forward_as_tuple(std::make_shared(breakp))); + child = pair.first->second; } return child; } void WildcardTreeNode::insert(const std::string &str) { - WildcardTreeNode* cur = this; + std::shared_ptr cur = static_self_cast(); size_t length = str.length() - 1; for (size_t pos = 0; pos < length; ++pos) { @@ -52,9 +52,9 @@ void WildcardTreeNode::insert(const std::string &str) { } void WildcardTreeNode::remove(const std::string &str) { - WildcardTreeNode* cur = this; + std::shared_ptr cur = static_self_cast(); - std::stack path; + std::stack> path; path.push(cur); size_t len = str.length(); for (size_t pos = 0; pos < len; ++pos) { @@ -85,7 +85,7 @@ void WildcardTreeNode::remove(const std::string &str) { } ReturnValue WildcardTreeNode::findOne(const std::string &query, std::string &result) const { - const WildcardTreeNode* cur = this; + auto cur = static_self_cast(); for (char pos : query) { cur = cur->getChild(pos); if (!cur) { @@ -105,6 +105,6 @@ ReturnValue WildcardTreeNode::findOne(const std::string &query, std::string &res auto it = cur->children.begin(); result += it->first; - cur = &it->second; + cur = it->second; } while (true); } diff --git a/src/utils/wildcardtree.hpp b/src/utils/wildcardtree.hpp index 07728ae9849..9f3d2cf8ece 100644 --- a/src/utils/wildcardtree.hpp +++ b/src/utils/wildcardtree.hpp @@ -11,19 +11,19 @@ #include "declarations.hpp" -class WildcardTreeNode { +class WildcardTreeNode : public SharedObject { public: explicit WildcardTreeNode(bool initBreakpoint) : breakpoint(initBreakpoint) { } - WildcardTreeNode(WildcardTreeNode &&other) = default; + WildcardTreeNode(WildcardTreeNode &&other) noexcept = default; // non-copyable WildcardTreeNode(const WildcardTreeNode &) = delete; WildcardTreeNode &operator=(const WildcardTreeNode &) = delete; - WildcardTreeNode* getChild(char ch); - const WildcardTreeNode* getChild(char ch) const; - WildcardTreeNode* addChild(char ch, bool breakpoint); + std::shared_ptr getChild(char ch); + std::shared_ptr getChild(char ch) const; + std::shared_ptr addChild(char ch, bool breakpoint); void insert(const std::string &str); void remove(const std::string &str); @@ -31,6 +31,6 @@ class WildcardTreeNode { ReturnValue findOne(const std::string &query, std::string &result) const; private: - std::map children; + std::map> children; bool breakpoint; }; diff --git a/vcpkg.json b/vcpkg.json index 82f1058bd94..a0bc4a0332b 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -9,7 +9,6 @@ "bext-ut", "curl", "eventpp", - "jsoncpp", "luajit", "magic-enum", "mio", diff --git a/vcproj/settings.props b/vcproj/settings.props index 35625d790b9..6f98969614d 100644 --- a/vcproj/settings.props +++ b/vcproj/settings.props @@ -21,7 +21,6 @@ libcurl.lib; fmt.lib; spdlog.lib; - jsoncpp.lib; abseil_dll.lib; argon2.lib; opentelemetry_common.lib; @@ -60,7 +59,6 @@ libcurl-d.lib; fmtd.lib; spdlogd.lib; - jsoncpp.lib; abseil_dll.lib; argon2.lib; opentelemetry_common.lib; From 0c0e5467b5f35a2404c5052e7ec3402fc84f1992 Mon Sep 17 00:00:00 2001 From: Beats Date: Mon, 1 Apr 2024 11:57:45 -0400 Subject: [PATCH 09/21] feat: disable metrics at compile-time (#2509) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To install the libraries, need to run the following commands: For Windows systems (with static linking): • vcpkg install opentelemetry-cpp[default-features,otlp-http,prometheus] --triplet x64-windows-static For Windows systems (with dynamic linking): • vcpkg install opentelemetry-cpp[default-features,otlp-http,prometheus] --triplet x64-windows For Linux systems: • vcpkg install opentelemetry-cpp[default-features,otlp-http,prometheus] --triplet x64-linux --- CMakeLists.txt | 7 ++ cmake/modules/BaseConfig.cmake | 6 +- cmake/modules/CanaryLib.cmake | 24 ++++--- src/canary_server.cpp | 3 +- src/lib/CMakeLists.txt | 5 +- src/lib/metrics/metrics.cpp | 9 ++- src/lib/metrics/metrics.hpp | 127 +++++++++++++++++++++++---------- src/pch.hpp | 15 ++++ vcpkg.json | 8 --- 9 files changed, 144 insertions(+), 60 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cf201ce38f..e4093f4de2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,11 +48,18 @@ include(LoggingHelper) option(OPTIONS_ENABLE_CCACHE "Enable ccache" OFF) option(OPTIONS_ENABLE_SCCACHE "Use sccache to speed up compilation process" OFF) option(OPTIONS_ENABLE_IPO "Check and Enable interprocedural optimization (IPO/LTO)" ON) +option(FEATURE_METRICS "Enable metrics feature" OFF) # ***************************************************************************** # Options Code # ***************************************************************************** +if(FEATURE_METRIC) + log_option_enabled("metrics") +else () + log_option_disabled("metrics") +endif () + # === CCACHE === if(OPTIONS_ENABLE_CCACHE) find_program(CCACHE ccache) diff --git a/cmake/modules/BaseConfig.cmake b/cmake/modules/BaseConfig.cmake index 6a8ce69ed4b..7e3f6404b3f 100644 --- a/cmake/modules/BaseConfig.cmake +++ b/cmake/modules/BaseConfig.cmake @@ -32,8 +32,10 @@ find_package(absl CONFIG REQUIRED) find_package(asio CONFIG REQUIRED) find_package(eventpp CONFIG REQUIRED) find_package(magic_enum CONFIG REQUIRED) -find_package(opentelemetry-cpp CONFIG REQUIRED) -find_package(prometheus-cpp CONFIG REQUIRED) +if(FEATURE_METRICS) + find_package(opentelemetry-cpp CONFIG REQUIRED) + find_package(prometheus-cpp CONFIG REQUIRED) +endif() find_package(mio REQUIRED) find_package(pugixml CONFIG REQUIRED) find_package(spdlog REQUIRED) diff --git a/cmake/modules/CanaryLib.cmake b/cmake/modules/CanaryLib.cmake index 270bbf59a99..a3f5410b9d8 100644 --- a/cmake/modules/CanaryLib.cmake +++ b/cmake/modules/CanaryLib.cmake @@ -105,17 +105,25 @@ target_link_libraries(${PROJECT_NAME}_lib unofficial::argon2::libargon2 unofficial::libmariadb unofficial::mariadbclient - opentelemetry-cpp::common - opentelemetry-cpp::metrics - opentelemetry-cpp::api - opentelemetry-cpp::ext - opentelemetry-cpp::sdk - opentelemetry-cpp::logs - opentelemetry-cpp::ostream_metrics_exporter - opentelemetry-cpp::prometheus_exporter protobuf ) +if(FEATURE_METRICS) + add_definitions(-DFEATURE_METRICS) + + target_link_libraries(${PROJECT_NAME}_lib + PUBLIC + opentelemetry-cpp::common + opentelemetry-cpp::metrics + opentelemetry-cpp::api + opentelemetry-cpp::ext + opentelemetry-cpp::sdk + opentelemetry-cpp::logs + opentelemetry-cpp::ostream_metrics_exporter + opentelemetry-cpp::prometheus_exporter + ) +endif() + if(CMAKE_BUILD_TYPE MATCHES Debug) target_link_libraries(${PROJECT_NAME}_lib PUBLIC ${ZLIB_LIBRARY_DEBUG}) else() diff --git a/src/canary_server.cpp b/src/canary_server.cpp index 56cd53bf567..0961bc93fde 100644 --- a/src/canary_server.cpp +++ b/src/canary_server.cpp @@ -61,6 +61,7 @@ int CanaryServer::run() { loadConfigLua(); logger.info("Server protocol: {}.{}{}", CLIENT_VERSION_UPPER, CLIENT_VERSION_LOWER, g_configManager().getBoolean(OLD_PROTOCOL, __FUNCTION__) ? " and 10x allowed!" : ""); +#ifdef FEATURE_METRICS metrics::Options metricsOptions; metricsOptions.enablePrometheusExporter = g_configManager().getBoolean(METRICS_ENABLE_PROMETHEUS, __FUNCTION__); if (metricsOptions.enablePrometheusExporter) { @@ -71,7 +72,7 @@ int CanaryServer::run() { metricsOptions.ostreamOptions.export_interval_millis = std::chrono::milliseconds(g_configManager().getNumber(METRICS_OSTREAM_INTERVAL, __FUNCTION__)); } g_metrics().init(metricsOptions); - +#endif rsa.start(); initializeDatabase(); loadModules(); diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 402c6a34a79..55709c59ac3 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,6 +1,9 @@ target_sources(${PROJECT_NAME}_lib PRIVATE di/soft_singleton.cpp logging/log_with_spd_log.cpp - metrics/metrics.cpp thread/thread_pool.cpp ) + +if(FEATURE_METRICS) + target_sources(${PROJECT_NAME}_lib PRIVATE metrics/metrics.cpp) +endif() diff --git a/src/lib/metrics/metrics.cpp b/src/lib/metrics/metrics.cpp index 2a65e9a7d5d..cf11060125a 100644 --- a/src/lib/metrics/metrics.cpp +++ b/src/lib/metrics/metrics.cpp @@ -1,3 +1,4 @@ +#ifdef FEATURE_METRICS /** * Canary - A free and open-source MMORPG server emulator * Copyright (©) 2019-2024 OpenTibiaBR @@ -7,8 +8,8 @@ * Website: https://docs.opentibiabr.com/ */ -#include "metrics.hpp" -#include "lib/di/container.hpp" + #include "metrics.hpp" + #include "lib/di/container.hpp" using namespace metrics; @@ -41,7 +42,7 @@ void Metrics::init(Options opts) { initHistograms(); } -void Metrics ::initHistograms() { +void Metrics::initHistograms() { for (auto name : latencyNames) { auto instrumentSelector = metrics_sdk::InstrumentSelectorFactory::Create(metrics_sdk::InstrumentType::kHistogram, name, "us"); auto meterSelector = metrics_sdk::MeterSelectorFactory::Create("performance", otelVersion, otelSchema); @@ -108,3 +109,5 @@ void ScopedLatency::stop() { auto attrskv = opentelemetry::common::KeyValueIterableView { attrs }; histogram->Record(elapsed, attrskv, context); } + +#endif // FEATURE_METRICS diff --git a/src/lib/metrics/metrics.hpp b/src/lib/metrics/metrics.hpp index 0d8c291dfbe..279ea5f91c5 100644 --- a/src/lib/metrics/metrics.hpp +++ b/src/lib/metrics/metrics.hpp @@ -9,43 +9,29 @@ #pragma once -#include "game/scheduling/dispatcher.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#ifdef FEATURE_METRICS + #include "game/scheduling/dispatcher.hpp" + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include namespace metrics_sdk = opentelemetry::sdk::metrics; namespace common = opentelemetry::common; namespace metrics_exporter = opentelemetry::exporter::metrics; namespace metrics_api = opentelemetry::metrics; -constexpr std::string_view methodName(const char* s) { - std::string_view prettyFunction(s); - size_t bracket = prettyFunction.rfind("("); - size_t space = prettyFunction.rfind(" ", bracket) + 1; - return prettyFunction.substr(space, bracket - space); -} - -#if defined(__GNUC__) || defined(__clang__) - #define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__) -#elif defined(_MSC_VER) - #define __METHOD_NAME__ methodName(__FUNCSIG__) -#else - #error "Compiler not supported" -#endif - namespace metrics { using Meter = opentelemetry::nostd::shared_ptr; @@ -85,12 +71,12 @@ namespace metrics { bool stopped { false }; }; -#define DEFINE_LATENCY_CLASS(class_name, histogram_name, category) \ - class class_name##_latency final : public ScopedLatency { \ - public: \ - class_name##_latency(std::string_view name) : \ - ScopedLatency(name, histogram_name "_latency", category) { } \ - } + #define DEFINE_LATENCY_CLASS(class_name, histogram_name, category) \ + class class_name##_latency final : public ScopedLatency { \ + public: \ + class_name##_latency(std::string_view name) : \ + ScopedLatency(name, histogram_name "_latency", category) { } \ + } DEFINE_LATENCY_CLASS(method, "method", "method"); DEFINE_LATENCY_CLASS(lua, "lua", "scope"); @@ -170,3 +156,70 @@ namespace metrics { constexpr auto g_metrics = metrics::Metrics::getInstance; + +#else // FEATURE_METRICS + + #include "lib/di/container.hpp" + +struct Options { + bool enablePrometheusExporter; + bool enableOStreamExporter; +}; + +class ScopedLatency { +public: + explicit ScopedLatency([[maybe_unused]] std::string_view name, [[maybe_unused]] const std::string &histogramName, [[maybe_unused]] const std::string &scopeKey) {}; + explicit ScopedLatency([[maybe_unused]] std::string_view name, [[maybe_unused]] std::set &histogram, [[maybe_unused]] const std::map &attrs = {}, [[maybe_unused]] const std::string &context = std::string()) {}; + + void stop() {}; + + ~ScopedLatency() = default; +}; + +namespace metrics { + #define DEFINE_LATENCY_CLASS(class_name, histogram_name, category) \ + class class_name##_latency final : public ScopedLatency { \ + public: \ + class_name##_latency(std::string_view name) : \ + ScopedLatency(name, histogram_name "_latency", category) { } \ + } + + DEFINE_LATENCY_CLASS(method, "method", "method"); + DEFINE_LATENCY_CLASS(lua, "lua", "scope"); + DEFINE_LATENCY_CLASS(query, "query", "truncated_query"); + DEFINE_LATENCY_CLASS(task, "task", "task"); + DEFINE_LATENCY_CLASS(lock, "lock", "scope"); + + const std::vector latencyNames { + "method_latency", + "lua_latency", + "query_latency", + "task_latency", + "lock_latency", + }; + + class Metrics final { + public: + Metrics() = default; + ~Metrics() = default; + + void init([[maybe_unused]] Options opts) {}; + void initHistograms() {}; + void shutdown() {}; + + static Metrics &getInstance() { + return inject(); + }; + + void addCounter([[maybe_unused]] std::string_view name, [[maybe_unused]] double value, [[maybe_unused]] const std::map &attrs = {}) { } + + void addUpDownCounter([[maybe_unused]] std::string_view name, [[maybe_unused]] int value, [[maybe_unused]] const std::map &attrs = {}) { } + + friend class ScopedLatency; + }; +} + +constexpr auto g_metrics + = metrics::Metrics::getInstance; + +#endif // FEATURE_METRICS diff --git a/src/pch.hpp b/src/pch.hpp index 7c38a99ee94..e69c27016a4 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -170,3 +170,18 @@ struct fmt::formatter, char>> : formatter< #include #include "lua/global/shared_object.hpp" + +constexpr std::string_view methodName(const char* s) { + std::string_view prettyFunction(s); + size_t bracket = prettyFunction.rfind('('); + size_t space = prettyFunction.rfind(' ', bracket) + 1; + return prettyFunction.substr(space, bracket - space); +} + +#if defined(__GNUC__) || defined(__clang__) + #define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__) +#elif defined(_MSC_VER) + #define __METHOD_NAME__ methodName(__FUNCSIG__) +#else + #error "Compiler not supported" +#endif diff --git a/vcpkg.json b/vcpkg.json index a0bc4a0332b..dda054f3774 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -12,14 +12,6 @@ "luajit", "magic-enum", "mio", - { - "name": "opentelemetry-cpp", - "default-features": true, - "features": [ - "otlp-http", - "prometheus" - ] - }, "parallel-hashmap", "protobuf", "pugixml", From 8479c168913ec423be23bb4e7328d631748afb6f Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Tue, 2 Apr 2024 16:38:41 -0300 Subject: [PATCH 10/21] fix: transform item logic crash (#2517) Resolves #2516 Related to: #2419 In the updated version of the code, we streamlined the condition for item decay by integrating an additional check directly into the initial if statement. Previously, we had a separate check inside the if block to determine if the newType.decayTo value was present, which then set the itemId accordingly. However, this approach had the potential risk of creating unnecessary complexity and possibly leading to a loop if the conditions weren't met as expected. To address this and enhance clarity, we've moved the check for newType.decayTo into the condition of the if statement itself. This adjustment ensures that all necessary conditions are evaluated upfront, making the code more straightforward and preventing the execution from entering the if block unless all criteria are satisfied. This change not only simplifies the logic but also ensures that we avoid any unintended loops by making the transition to the else if statement more predictable when the initial conditions are not met. --- src/game/game.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index 9310f1c9a20..cac0b596ebf 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -2616,12 +2616,10 @@ std::shared_ptr Game::transformItem(std::shared_ptr item, uint16_t n auto decaying = item->getDecaying(); // If the item is decaying, we need to transform it to the new item - if (decaying > DECAYING_FALSE && item->getDuration() <= 1) { + if (decaying > DECAYING_FALSE && item->getDuration() <= 1 && newType.decayTo) { g_logger().debug("Decay duration old type {}, transformEquipTo {}, transformDeEquipTo {}", curType.decayTo, curType.transformEquipTo, curType.transformDeEquipTo); - g_logger().debug("Decay duration new type, decayTo {}, transformEquipTo {}, transformDeEquipTo {}", newType.decayTo, newType.transformEquipTo, newType.transformDeEquipTo); - if (newType.decayTo) { - itemId = newType.decayTo; - } + g_logger().debug("Decay duration new type decayTo {}, transformEquipTo {}, transformDeEquipTo {}", newType.decayTo, newType.transformEquipTo, newType.transformDeEquipTo); + itemId = newType.decayTo; } else if (curType.id != newType.id) { if (newType.group != curType.group) { item->setDefaultSubtype(); From 0bb10ab2cc5c83657a495601f21835e26d173b83 Mon Sep 17 00:00:00 2001 From: Jeswill David Bolivar Mendoza <76903590+jeswilldbm@users.noreply.github.com> Date: Tue, 2 Apr 2024 22:42:54 +0200 Subject: [PATCH 11/21] fix: prismatic ring attribute absorb (#2522) --- data/items/items.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/items/items.xml b/data/items/items.xml index b1a1c6b003f..765c6e9db51 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -34797,7 +34797,7 @@ - + From c15430ade5b842bc8061c0fc7365dcd70dad1446 Mon Sep 17 00:00:00 2001 From: Jeswill David Bolivar Mendoza <76903590+jeswilldbm@users.noreply.github.com> Date: Thu, 4 Apr 2024 16:48:18 +0200 Subject: [PATCH 12/21] fix: forge convergence show all items with same class (#2521) --- src/server/network/protocol/protocolgame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 218fc857d3c..0d0d8e79f17 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -5021,7 +5021,7 @@ void ProtocolGame::sendOpenForge() { getForgeInfoMap(item, receiveTierItemMap); } if (itemClassification == 4) { - getForgeInfoMap(item, convergenceItemsMap[item->getSlotPosition()]); + getForgeInfoMap(item, convergenceItemsMap[item->getClassification()]); } } } From 167bae5c750d23bcec26b527279b32cb65db84cd Mon Sep 17 00:00:00 2001 From: Luan Luciano Date: Thu, 4 Apr 2024 11:48:45 -0300 Subject: [PATCH 13/21] fix: problem with casks items in the charge loop and adjustment without code (#2505) --- data/modules/scripts/gamestore/init.lua | 236 +++++++++++++----------- 1 file changed, 124 insertions(+), 112 deletions(-) diff --git a/data/modules/scripts/gamestore/init.lua b/data/modules/scripts/gamestore/init.lua index a927715cd93..6146f562307 100644 --- a/data/modules/scripts/gamestore/init.lua +++ b/data/modules/scripts/gamestore/init.lua @@ -402,7 +402,7 @@ function parseBuyStoreOffer(playerId, msg) -- All guarding conditions under which the offer should not be processed must be included here if - (table.contains(GameStore.OfferTypes, offer.type) == false) -- we've got an invalid offer type + not table.contains(GameStore.OfferTypes, offer.type) -- we've got an invalid offer type or not player or (player:getVocation():getId() == 0) and (not GameStore.haveOfferRook(id)) -- we don't have such offer or not offer @@ -620,7 +620,7 @@ end function Player.canBuyOffer(self, offer) local playerId = self:getId() local disabled, disabledReason = 0, "" - if offer.disabled == true or not offer.type then + if offer.disabled or not offer.type then disabled = 1 end @@ -692,8 +692,7 @@ function Player.canBuyOffer(self, offer) disabledReason = "The offer is fake." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_MOUNT then - local hasMount = self:hasMount(offer.id) - if hasMount == true then + if self:hasMount(offer.id) then disabled = 1 disabledReason = "You already have this mount." end @@ -723,12 +722,11 @@ function Player.canBuyOffer(self, offer) disabledReason = "You already have 3 slots released." end elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_EXPBOOST then - local remainingBoost = self:getExpBoostStamina() if self:getStorageValue(GameStore.Storages.expBoostCount) == 6 then disabled = 1 disabledReason = "You can't buy XP Boost for today." end - if remainingBoost > 0 then + if self:getExpBoostStamina() > 0 then disabled = 1 disabledReason = "You already have an active XP boost." end @@ -786,9 +784,9 @@ function Player.canReceiveStoreItems(self, offerId, offerCount) local inboxItems = inbox:getItems(true) local slotsOccupied = #inboxItems local maxCapacity = inbox:getMaxCapacity() - local slotsAvailable = maxCapacity - slotsOccupied if slotsOccupied + slotsNeeded > maxCapacity then + local slotsAvailable = maxCapacity - slotsOccupied return false, string.format("Not enough free slots in your store inbox. You need %d more slot(s). Currently occupied: %d/%d", slotsNeeded - slotsAvailable, slotsOccupied, maxCapacity) end @@ -1104,14 +1102,16 @@ function sendStoreTransactionHistory(playerId, page, entriesPerPage) if not player then return false end - local oldProtocol = player:getClient().version < 1200 - local totalEntries = GameStore.retrieveHistoryTotalPages(player:getAccountId()) - local totalPages = math.ceil(totalEntries / entriesPerPage) + local entries = GameStore.retrieveHistoryEntries(player:getAccountId(), page, entriesPerPage) -- this makes everything easy! if #entries == 0 then return addPlayerEvent(sendStoreError, 250, playerId, GameStore.StoreErrors.STORE_ERROR_HISTORY, "You don't have any entries yet.") end + local oldProtocol = player:getClient().version < 1200 + local totalEntries = GameStore.retrieveHistoryTotalPages(player:getAccountId()) + local totalPages = math.ceil(totalEntries / entriesPerPage) + local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_OpenTransactionHistory) msg:addU32(totalPages > 0 and page - 1 or 0x0) -- current page @@ -1165,10 +1165,8 @@ function sendStoreError(playerId, errorType, message) local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_StoreError) - msg:addByte(errorType) msg:addString(message, "sendStoreError - message") - msg:sendToPlayer(player) end @@ -1183,7 +1181,7 @@ function sendStoreBalanceUpdating(playerId, updating) msg:addByte(0x00) msg:sendToPlayer(player) - if updating == true then + if updating then sendUpdatedStoreBalances(playerId) end end @@ -1194,7 +1192,6 @@ function sendUpdatedStoreBalances(playerId) return false end - local oldProtocol = player:getClient().version < 1200 local msg = NetworkMessage() msg:addByte(GameStore.SendingPackets.S_CoinBalanceUpdating) msg:addByte(0x01) @@ -1205,6 +1202,8 @@ function sendUpdatedStoreBalances(playerId) -- Send total of coins (transferable and normal coin) msg:addU32(player:getTibiaCoins()) msg:addU32(player:getTransferableCoins()) -- How many are Transferable + + local oldProtocol = player:getClient().version < 1200 if not oldProtocol then -- How many are reserved for a Character Auction -- We currently do not have this system implemented, so we will send 0 @@ -1346,7 +1345,7 @@ end GameStore.retrieveHistoryTotalPages = function(accountId) local resultId = db.storeQuery("SELECT count(id) as total FROM store_history WHERE account_id = " .. accountId) - if resultId == false then + if not resultId then return 0 end @@ -1360,7 +1359,7 @@ GameStore.retrieveHistoryEntries = function(accountId, currentPage, entriesPerPa local offset = currentPage > 1 and entriesPerPage * (currentPage - 1) or 0 local resultId = db.storeQuery("SELECT * FROM `store_history` WHERE `account_id` = " .. accountId .. " ORDER BY `time` DESC LIMIT " .. offset .. ", " .. entriesPerPage .. ";") - if resultId ~= false then + if resultId then repeat local entry = { mode = Result.getNumber(resultId, "mode"), @@ -1602,7 +1601,7 @@ function GameStore.processStackablePurchase(player, offerId, offerCount, offerNa local countToAdd = math.min(remainingCount, stackSize) local inboxItem = inbox:addItem(offerId, countToAdd) if inboxItem then - if movable ~= true then + if not movable then inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) end else @@ -1631,21 +1630,32 @@ function GameStore.processHouseRelatedPurchase(player, offer) local inbox = player:getStoreInbox() if inbox then for _, itemId in ipairs(itemIds) do - for i = 1, offer.count do + if isCaskItem(itemId) then local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) if decoKit then decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item in the Store.\nUnwrap it in your own house to create a <" .. ItemType(itemId):getName() .. ">.") decoKit:setCustomAttribute("unWrapId", itemId) - if isCaskItem(itemId) then - decoKit:setAttribute(ITEM_ATTRIBUTE_DATE, offer.count) - end + decoKit:setAttribute(ITEM_ATTRIBUTE_DATE, offer.count) - if offer.movable ~= true then + if not offer.movable then decoKit:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) end end + player:sendUpdateContainer(inbox) + else + for i = 1, offer.count do + local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1) + if decoKit then + decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item in the Store.\nUnwrap it in your own house to create a <" .. ItemType(itemId):getName() .. ">.") + decoKit:setCustomAttribute("unWrapId", itemId) + + if not offer.movable then + decoKit:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) + end + end + player:sendUpdateContainer(inbox) + end end - player:sendUpdateContainer(inbox) end end end @@ -1689,8 +1699,6 @@ function GameStore.processMountPurchase(player, offerId) end function GameStore.processNameChangePurchase(player, offer, productType, newName) - local playerId = player:getId() - if productType == GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE then local tile = Tile(player:getPosition()) if tile then @@ -1720,11 +1728,11 @@ function GameStore.processNameChangePurchase(player, offer, productType, newName else message = "Your character has been renamed successfully." end - addPlayerEvent(sendStorePurchaseSuccessful, 500, playerId, message) + addPlayerEvent(sendStorePurchaseSuccessful, 500, player:getId(), message) player:changeName(newName) else - return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) + return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) end end @@ -1780,9 +1788,6 @@ function GameStore.processTempleTeleportPurchase(player) end function GameStore.processHirelingPurchase(player, offer, productType, hirelingName, chosenSex) - local playerId = player:getId() - local offerId = offer.id - if player:getClient().version < 1200 then return error({ code = 1, message = "You cannot buy hirelings on client 10, please relog on client 12 and try again." }) end @@ -1804,7 +1809,7 @@ function GameStore.processHirelingPurchase(player, offer, productType, hirelingN player:makeCoinTransaction(offer, hirelingName) local message = "You have successfully bought " .. hirelingName - return addPlayerEvent(sendStorePurchaseSuccessful, 650, playerId, message) + return addPlayerEvent(sendStorePurchaseSuccessful, 650, player:getId(), message) -- If not, we ask him to do! else if player:getHirelingsCount() >= 10 then @@ -1812,14 +1817,50 @@ function GameStore.processHirelingPurchase(player, offer, productType, hirelingN end -- TODO: Use the correct dialog (byte 0xDB) on client 1205+ -- for compatibility, request name using the change name dialog - return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_HIRELING) + return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_HIRELING) end end -function GameStore.processHirelingChangeNamePurchase(player, offer, productType, newHirelingName) - local playerId = player:getId() - local offerId = offer.id +-- Hireling Helpers +local function HandleHirelingNameChange(playerId, offer, newHirelingName) + local player = Player(playerId) + if not player then + return + end + + local functionCallback = function(playerIdInFunction, data, hireling) + local playerInFunction = Player(playerIdInFunction) + if not playerInFunction then + return + end + + if not hireling then + return playerInFunction:showInfoModal("Error", "Your must select a hireling.") + end + if hireling.active > 0 then + return playerInFunction:showInfoModal("Error", "Your hireling must be inside his/her lamp.") + end + + local oldName = hireling.name + hireling.name = data.newHirelingName + + if not playerInFunction:makeCoinTransaction(data.offer, oldName .. " to " .. hireling.name) then + return playerInFunction:showInfoModal("Error", "Transaction error") + end + + local lamp = playerInFunction:findHirelingLamp(hireling:getId()) + if lamp then + lamp:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "This mysterious lamp summons your very own personal hireling.\nThis item cannot be traded.\nThis magic lamp is the home of " .. hireling:getName() .. ".") + end + logger.debug("{} has been renamed to {}", oldName, hireling.name) + sendUpdatedStoreBalances(playerIdInFunction) + end + + player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", functionCallback, { offer = offer, newHirelingName = newHirelingName }) +end + +function GameStore.processHirelingChangeNamePurchase(player, offer, productType, newHirelingName) if player:getClient().version < 1200 then return error({ code = 1, @@ -1838,17 +1879,60 @@ function GameStore.processHirelingChangeNamePurchase(player, offer, productType, end) local message = "Close the store window to select which hireling should be renamed to " .. newHirelingName + local playerId = player:getId() addPlayerEvent(sendStorePurchaseSuccessful, 200, playerId, message) - addPlayerEvent(HandleHirelingNameChange, 550, playerId, offer, newHirelingName) else - return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) + return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE) end end -function GameStore.processHirelingChangeSexPurchase(player, offer) - local playerId = player:getId() +local function HandleHirelingSexChange(playerId, offer) + local player = Player(playerId) + if not player then + return + end + + local functionCallback = function(playerIdInFunction, data, hireling) + local playerInFunction = Player(playerIdInFunction) + if not playerInFunction then + return + end + + if not hireling then + return playerInFunction:showInfoModal("Error", "Your must select a hireling.") + end + if hireling.active > 0 then + return playerInFunction:showInfoModal("Error", "Your hireling must be inside his/her lamp.") + end + + if not playerInFunction:makeCoinTransaction(data.offer, hireling:getName()) then + return playerInFunction:showInfoModal("Error", "Transaction error") + end + + local changeTo, sexString, lookType + if hireling.sex == HIRELING_SEX.FEMALE then + changeTo = HIRELING_SEX.MALE + sexString = "male" + lookType = HIRELING_OUTFIT_DEFAULT.male + else + changeTo = HIRELING_SEX.FEMALE + sexString = "female" + lookType = HIRELING_OUTFIT_DEFAULT.female + end + + hireling.sex = changeTo + hireling.looktype = lookType + + logger.debug("{} sex was changed to {}", hireling:getName(), sexString) + sendUpdatedStoreBalances(playerIdInFunction) + end + + player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", functionCallback, { offer = offer }) +end + +function GameStore.processHirelingChangeSexPurchase(player, offer) if player:getClient().version < 1200 then return error({ code = 1, @@ -1857,8 +1941,8 @@ function GameStore.processHirelingChangeSexPurchase(player, offer) end local message = "Close the store window to select which hireling should have the sex changed." + local playerId = player:getId() addPlayerEvent(sendStorePurchaseSuccessful, 200, playerId, message) - addPlayerEvent(HandleHirelingSexChange, 550, playerId, offer) end @@ -2154,75 +2238,3 @@ function Player:openStore(serviceName) --exporting the method so other scripts c addPlayerEvent(sendShowStoreOffers, 50, playerId, category) end end - --- Hireling Helpers -function HandleHirelingNameChange(playerId, offer, newHirelingName) - local player = Player(playerId) - - local cb = function(playerId, data, hireling) - local offer = data.offer - local newHirelingName = data.newHirelingName - local player = Player(playerId) - if not hireling then - return player:showInfoModal("Error", "Your must select a hireling.") - end - - if hireling.active > 0 then - return player:showInfoModal("Error", "Your hireling must be inside his/her lamp.") - end - - local oldName = hireling.name - hireling.name = newHirelingName - - if not player:makeCoinTransaction(data.offer, oldName .. " to " .. newHirelingName) then - return player:showInfoModal("Error", "Transaction error") - end - - local lamp = player:findHirelingLamp(hireling:getId()) - if lamp then - lamp:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "This mysterious lamp summons your very own personal hireling.\nThis item cannot be traded.\nThis magic lamp is the home of " .. hireling:getName() .. ".") - end - logger.debug("{} has been renamed to {}", oldName, newHirelingName) - sendUpdatedStoreBalances(playerId) - end - - player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", cb, { offer = offer, newHirelingName = newHirelingName }) -end - -function HandleHirelingSexChange(playerId, offer) - local player = Player(playerId) - - local cb = function(playerId, data, hireling) - local player = Player(playerId) - if not hireling then - return player:showInfoModal("Error", "Your must select a hireling.") - end - - if hireling.active > 0 then - return player:showInfoModal("Error", "Your hireling must be inside his/her lamp.") - end - - if not player:makeCoinTransaction(data.offer, hireling:getName()) then - return player:showInfoModal("Error", "Transaction error") - end - - local changeTo, sexString, lookType - if hireling.sex == HIRELING_SEX.FEMALE then - changeTo = HIRELING_SEX.MALE - sexString = "male" - lookType = HIRELING_OUTFIT_DEFAULT.male - else - changeTo = HIRELING_SEX.FEMALE - sexString = "female" - lookType = HIRELING_OUTFIT_DEFAULT.female - end - - hireling.sex = changeTo - hireling.looktype = lookType - - logger.debug("{} sex was changed to {}", hireling:getName(), sexString) - sendUpdatedStoreBalances(playerId) - end - - player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", cb, { offer = offer }) -end From 0f6cc07b198da44bfa862fe111a0e5cded130ba3 Mon Sep 17 00:00:00 2001 From: Karin Date: Mon, 15 Apr 2024 21:44:55 -0300 Subject: [PATCH 14/21] fix: incorrect id of bolt on npss asnarus and hireling (#2541) --- data-otservbr-global/npc/asnarus.lua | 2 +- data-otservbr-global/npc/hireling.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data-otservbr-global/npc/asnarus.lua b/data-otservbr-global/npc/asnarus.lua index a733d90834b..3992d513e9b 100644 --- a/data-otservbr-global/npc/asnarus.lua +++ b/data-otservbr-global/npc/asnarus.lua @@ -56,7 +56,7 @@ npcConfig.shop = { { itemName = "animate dead rune", clientId = 3203, buy = 375 }, { itemName = "arrow", clientId = 3447, buy = 2 }, { itemName = "blue quiver", clientId = 35848, buy = 400 }, - { itemName = "bolt", clientId = 3483, buy = 4 }, + { itemName = "bolt", clientId = 3446, buy = 4 }, { itemName = "bow", clientId = 3350, buy = 400, sell = 100 }, { itemName = "bowl of terror sweat", clientId = 20204, sell = 500 }, { itemName = "broken visor", clientId = 20184, sell = 1900 }, diff --git a/data-otservbr-global/npc/hireling.lua b/data-otservbr-global/npc/hireling.lua index 145d846bd7e..aad7785079d 100644 --- a/data-otservbr-global/npc/hireling.lua +++ b/data-otservbr-global/npc/hireling.lua @@ -228,7 +228,7 @@ function createHirelingType(HirelingName) }, ["distance"] = { { itemName = "arrow", clientId = 3447, buy = 2 }, - { itemName = "bolt", clientId = 3483, buy = 4 }, + { itemName = "bolt", clientId = 3446, buy = 4 }, { itemName = "bow", clientId = 3350, buy = 400, sell = 100 }, { itemName = "crossbow", clientId = 3349, buy = 500, sell = 120 }, { itemName = "crystalline arrow", clientId = 15793, buy = 450 }, From 88414330c101c59281de769a8acbf7ef37678440 Mon Sep 17 00:00:00 2001 From: Karin Date: Wed, 17 Apr 2024 14:18:27 -0300 Subject: [PATCH 15/21] fix: remove deprecated conjure diamond/spectral (#2551) https://tibia.fandom.com/wiki/Updates/12.55.10451 --- .../conjuring/conjure_diamond_arrow.lua | 21 ------------------- .../conjuring/conjure_spectral_bolt.lua | 21 ------------------- 2 files changed, 42 deletions(-) delete mode 100644 data/scripts/spells/conjuring/conjure_diamond_arrow.lua delete mode 100644 data/scripts/spells/conjuring/conjure_spectral_bolt.lua diff --git a/data/scripts/spells/conjuring/conjure_diamond_arrow.lua b/data/scripts/spells/conjuring/conjure_diamond_arrow.lua deleted file mode 100644 index 2ab4bbe0647..00000000000 --- a/data/scripts/spells/conjuring/conjure_diamond_arrow.lua +++ /dev/null @@ -1,21 +0,0 @@ -local spell = Spell("instant") - -function spell.onCastSpell(creature, variant) - return creature:conjureItem(0, 25757, 100, CONST_ME_MAGIC_BLUE) -end - -spell:group("support") -spell:id(192) -spell:name("Conjure Diamond Arrow") -spell:words("exevo gran con hur") -spell:cooldown(2 * 1000) -spell:groupCooldown(2 * 1000) -spell:level(150) -spell:mana(1000) -spell:soul(0) -spell:isPremium(true) -spell:isSelfTarget(true) -spell:isAggressive(false) -spell:vocation("paladin;true", "royal paladin;true") -spell:needLearn(false) -spell:register() diff --git a/data/scripts/spells/conjuring/conjure_spectral_bolt.lua b/data/scripts/spells/conjuring/conjure_spectral_bolt.lua deleted file mode 100644 index 336eb423139..00000000000 --- a/data/scripts/spells/conjuring/conjure_spectral_bolt.lua +++ /dev/null @@ -1,21 +0,0 @@ -local spell = Spell("instant") - -function spell.onCastSpell(creature, variant) - return creature:conjureItem(0, 35902, 100, CONST_ME_MAGIC_BLUE) -end - -spell:group("support") -spell:id(193) -spell:name("Conjure Spectral Bolt") -spell:words("exevo gran con vis") -spell:cooldown(2 * 1000) -spell:groupCooldown(2 * 1000) -spell:level(150) -spell:mana(1000) -spell:soul(0) -spell:isPremium(true) -spell:isSelfTarget(true) -spell:isAggressive(false) -spell:vocation("paladin;true", "royal paladin;true") -spell:needLearn(false) -spell:register() From 533e9d617388e3c16f3cc6cf5074e27a43c4c9d1 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Wed, 17 Apr 2024 17:34:02 -0300 Subject: [PATCH 16/21] fix: check nullptr town (avoid crash if town not exist) (#2549) --- src/creatures/players/player.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 592db179071..855b48a782b 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -657,6 +657,11 @@ class Player final : public Creature, public Cylinder, public Bankable { return loginPosition; } const Position &getTemplePosition() const { + if (!town) { + static auto emptyPosition = Position(); + return emptyPosition; + } + return town->getTemplePosition(); } std::shared_ptr getTown() const { From d2d44cd4fa95a125a774d88771fe78b48a6a9457 Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Wed, 17 Apr 2024 13:38:22 -0700 Subject: [PATCH 17/21] feat: configurable party share range (#2539) Pretty small yet useful configuration feature to allow one to easily change party share ranges. The configuration is a float, default to 1.5 which is the same as cipbia. --- config.lua.dist | 2 ++ src/config/config_enums.hpp | 1 + src/config/configmanager.cpp | 1 + src/creatures/players/grouping/party.cpp | 9 ++++++--- src/creatures/players/grouping/party.hpp | 1 + 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/config.lua.dist b/config.lua.dist index a5bb3d73ca5..97dc347c8ee 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -212,6 +212,8 @@ wheelAtelierRevealGreaterCost = 6000000 familiarTime = 30 partyAutoShareExperience = true +-- partyShareRangeMultiplier: the range of the party share experience, default 3/2 (1.5) +partyShareRangeMultiplier = 1.5 partyShareLootBoosts = false partyShareLootBoostsDimishingFactor = 0.7 diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp index b9b857f435c..dc3271daaf9 100644 --- a/src/config/config_enums.hpp +++ b/src/config/config_enums.hpp @@ -178,6 +178,7 @@ enum ConfigKey_t : uint16_t { OWNER_NAME, PARALLELISM, PARTY_AUTO_SHARE_EXPERIENCE, + PARTY_SHARE_RANGE_MULTIPLIER, PARTY_LIST_MAX_DISTANCE, PARTY_SHARE_LOOT_BOOSTS_DIMINISHING_FACTOR, PARTY_SHARE_LOOT_BOOSTS, diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index c1702672e71..ac78a2bbcfb 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -317,6 +317,7 @@ bool ConfigManager::load() { loadIntConfig(L, STAMINA_PZ_GAIN, "staminaPzGain", 1); loadIntConfig(L, STAMINA_TRAINER_DELAY, "staminaTrainerDelay", 5); loadIntConfig(L, STAMINA_TRAINER_GAIN, "staminaTrainerGain", 1); + loadFloatConfig(L, PARTY_SHARE_RANGE_MULTIPLIER, "partyShareRangeMultiplier", 1.5f); loadIntConfig(L, START_STREAK_LEVEL, "startStreakLevel", 0); loadIntConfig(L, STATUSQUERY_TIMEOUT, "statusTimeout", 5000); loadIntConfig(L, STORE_COIN_PACKET, "coinPacketSize", 25); diff --git a/src/creatures/players/grouping/party.cpp b/src/creatures/players/grouping/party.cpp index 880fc77594f..c7d6fd48363 100644 --- a/src/creatures/players/grouping/party.cpp +++ b/src/creatures/players/grouping/party.cpp @@ -491,6 +491,10 @@ SharedExpStatus_t Party::getMemberSharedExperienceStatus(std::shared_ptr return SHAREDEXP_OK; } +float Party::shareRangeMultiplier() const { + return g_configManager().getFloat(PARTY_SHARE_RANGE_MULTIPLIER, __FUNCTION__); +} + uint32_t Party::getHighestLevel() { auto leader = getLeader(); if (!leader) { @@ -507,7 +511,7 @@ uint32_t Party::getHighestLevel() { } uint32_t Party::getMinLevel() { - return static_cast(std::ceil((static_cast(getHighestLevel()) * 2) / 3)); + return static_cast(std::ceil(static_cast(getHighestLevel()) / shareRangeMultiplier())); } uint32_t Party::getLowestLevel() { @@ -525,7 +529,7 @@ uint32_t Party::getLowestLevel() { } uint32_t Party::getMaxLevel() { - return static_cast(std::floor((static_cast(getLowestLevel()) * 3) / 2)); + return static_cast(std::floor(static_cast(getLowestLevel()) * shareRangeMultiplier())); } bool Party::isPlayerActive(std::shared_ptr player) { @@ -533,7 +537,6 @@ bool Party::isPlayerActive(std::shared_ptr player) { if (it == ticksMap.end()) { return false; } - uint64_t timeDiff = OTSYS_TIME() - it->second; return timeDiff <= 2 * 60 * 1000; } diff --git a/src/creatures/players/grouping/party.hpp b/src/creatures/players/grouping/party.hpp index a356d1a032b..5da0f4e0647 100644 --- a/src/creatures/players/grouping/party.hpp +++ b/src/creatures/players/grouping/party.hpp @@ -133,6 +133,7 @@ class Party : public SharedObject { uint32_t getLowestLevel(); uint32_t getMinLevel(); uint32_t getMaxLevel(); + float shareRangeMultiplier() const; std::map ticksMap; From 582e286ffb2c57afa050a93c5ae308321009599a Mon Sep 17 00:00:00 2001 From: Luan Luciano Date: Wed, 17 Apr 2024 17:40:14 -0300 Subject: [PATCH 18/21] fix: potions add flask to player (#2538) --- data/scripts/actions/items/potions.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/data/scripts/actions/items/potions.lua b/data/scripts/actions/items/potions.lua index 02e92349363..473796d79df 100644 --- a/data/scripts/actions/items/potions.lua +++ b/data/scripts/actions/items/potions.lua @@ -89,10 +89,13 @@ function flaskPotion.onUse(player, item, fromPosition, target, toPosition, isHot local deactivatedFlasks = player:kv():get("talkaction.potions.flask") or false if not deactivatedFlasks then local container = Container(item:getParent().uid) - local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) - - if fromPosition.x == CONTAINER_POSITION and container ~= inbox and container:getEmptySlots() ~= 0 then - container:addItem(potion.flask, 1) + if container then + local storeInbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) + if fromPosition.x == CONTAINER_POSITION and container ~= storeInbox and container:getEmptySlots() ~= 0 then + container:addItem(potion.flask, 1) + else + player:addItem(potion.flask, 1) + end else Game.createItem(potion.flask, 1, fromPosition) end From c43338e5ee766fd6a699d79ca32a50d12c9dcefe Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 17 Apr 2024 17:42:23 -0300 Subject: [PATCH 19/21] feat: cupcakes (#2537) This introduces a new feature to the Cupcake item behavior in the game. With this update, each Cupcake can now only be consumed once every 10 minutes. This cooldown is unique to each Cupcake, meaning that different Cupcakes do not share this cooldown period with each other. --- data-otservbr-global/lib/core/storages.lua | 3 -- .../scripts/actions/other/cup_cakes.lua | 51 ------------------- .../actions/items/blueberry_cupcake.lua | 18 +++++++ data/scripts/actions/items/lemon_cupcake.lua | 24 +++++++++ .../actions/items/strawberry_cupcake.lua | 18 +++++++ 5 files changed, 60 insertions(+), 54 deletions(-) delete mode 100644 data-otservbr-global/scripts/actions/other/cup_cakes.lua create mode 100644 data/scripts/actions/items/blueberry_cupcake.lua create mode 100644 data/scripts/actions/items/lemon_cupcake.lua create mode 100644 data/scripts/actions/items/strawberry_cupcake.lua diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua index 69f1d7f7948..6ce29967451 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -106,7 +106,6 @@ Storage = { -- unused ExerciseDummyExhaust = 30029, SamsOldBackpack = 30030, SamsOldBackpackDoor = 30031, - StrawberryCupcake = 30032, ChayenneReward = 30033, SwampDiggingTimeout = 30034, HydraEggQuest = 30035, @@ -125,8 +124,6 @@ Storage = { Navigator = 30048, DwarvenLegs = 30049, PrinceDrazzakTime = 30050, - LemonCupcake = 30052, - BlueberryCupcake = 30053, -- Reserved in Global.Storage.FamiliarSummonEvent10 = 30054 -- Reserved in Global.Storage.FamiliarSummonEvent60 = 30055 ChayenneKeyTime = 30056, diff --git a/data-otservbr-global/scripts/actions/other/cup_cakes.lua b/data-otservbr-global/scripts/actions/other/cup_cakes.lua deleted file mode 100644 index a9d94dbaacd..00000000000 --- a/data-otservbr-global/scripts/actions/other/cup_cakes.lua +++ /dev/null @@ -1,51 +0,0 @@ -local data = { - [28484] = { - Type = "mana", - ExhaustStor = Storage.BlueberryCupcake, - timestamp = 10, - }, - [28485] = { - Type = "health", - ExhaustStor = Storage.StrawberryCupcake, - timestamp = 10, - }, - [28486] = { - Type = "skill", - ExhaustStor = Storage.LemonCupcake, - timestamp = 10, - }, -} - -local lemon = Condition(CONDITION_ATTRIBUTES) -lemon:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) -lemon:setParameter(CONDITION_PARAM_SKILL_DISTANCE, 10) - -local cupCakes = Action() - -function cupCakes.onUse(player, item, fromPos, itemEx, toPos) - local foundItem = data[item.itemid] - if not foundItem then - return - end - if (player:getStorageValue(foundItem.ExhaustStor)) < os.time() then - if foundItem.Type == "mana" then - player:addMana(player:getMaxMana()) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your mana has been refilled.") - elseif foundItem.Type == "health" then - player:addHealth(player:getMaxHealth()) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your health has been refilled.") - elseif foundItem.Type == "skill" then - player:addCondition(lemon) - player:sendTextMessage(MESSAGE_FAILURE, "You feel more focused.") - end - player:say("Mmmm.", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:setStorageValue(foundItem.ExhaustStor, os.time() + (foundItem.timestamp * 60)) - else - player:sendTextMessage(MESSAGE_FAILURE, "You need to wait before using it again.") - end - return true -end - -cupCakes:id(28484, 28485, 28486) -cupCakes:register() diff --git a/data/scripts/actions/items/blueberry_cupcake.lua b/data/scripts/actions/items/blueberry_cupcake.lua new file mode 100644 index 00000000000..f645e852101 --- /dev/null +++ b/data/scripts/actions/items/blueberry_cupcake.lua @@ -0,0 +1,18 @@ +local blueberryCupcake = Action() + +function blueberryCupcake.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:hasExhaustion("blueberry-cupcake-cooldown") then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait before using it again.") + return true + end + + player:addMana(player:getMaxMana()) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your mana has been refilled.") + player:say("Mmmm.", TALKTYPE_MONSTER_SAY) + player:setExhaustion("blueberry-cupcake-cooldown", 10 * 60) + item:remove(1) + return true +end + +blueberryCupcake:id(28484) +blueberryCupcake:register() diff --git a/data/scripts/actions/items/lemon_cupcake.lua b/data/scripts/actions/items/lemon_cupcake.lua new file mode 100644 index 00000000000..3cf085d8ad8 --- /dev/null +++ b/data/scripts/actions/items/lemon_cupcake.lua @@ -0,0 +1,24 @@ +local distanceCondition = Condition(CONDITION_ATTRIBUTES) +distanceCondition:setParameter(CONDITION_PARAM_BUFF_SPELL, 1) +distanceCondition:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000) +distanceCondition:setParameter(CONDITION_PARAM_SKILL_DISTANCE, 10) +distanceCondition:setParameter(CONDITION_PARAM_FORCEUPDATE, true) + +local lemonCupcake = Action() + +function lemonCupcake.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:hasExhaustion("lemon-cupcake-cooldown") then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait before using it again.") + return true + end + + player:addCondition(distanceCondition) + player:sendTextMessage(MESSAGE_FAILURE, "You feel more focused.") + player:say("Mmmm.", TALKTYPE_MONSTER_SAY) + player:setExhaustion("lemon-cupcake-cooldown", 10 * 60) + item:remove(1) + return true +end + +lemonCupcake:id(28486) +lemonCupcake:register() diff --git a/data/scripts/actions/items/strawberry_cupcake.lua b/data/scripts/actions/items/strawberry_cupcake.lua new file mode 100644 index 00000000000..7ee7ec75764 --- /dev/null +++ b/data/scripts/actions/items/strawberry_cupcake.lua @@ -0,0 +1,18 @@ +local strawberryCupcake = Action() + +function strawberryCupcake.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:hasExhaustion("strawberry-cupcake-cooldown") then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait before using it again.") + return true + end + + player:addHealth(player:getMaxHealth()) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your health has been refilled.") + player:say("Mmmm.", TALKTYPE_MONSTER_SAY) + player:setExhaustion("strawberry-cupcake-cooldown", 10 * 60) + item:remove(1) + return true +end + +strawberryCupcake:id(28485) +strawberryCupcake:register() From 6503aa4589ad4623f1b4d20e6b6269d2af961959 Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 17 Apr 2024 17:44:24 -0300 Subject: [PATCH 20/21] improve: bank transfer min town id (#2547) --- config.lua.dist | 2 ++ src/config/config_enums.hpp | 3 ++- src/config/configmanager.cpp | 7 ++++--- src/game/bank/bank.cpp | 8 +++++--- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/config.lua.dist b/config.lua.dist index 97dc347c8ee..0507b652e29 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -241,6 +241,7 @@ onlyPremiumAccount = false -- NOTE: enablePlayerPutItemInAmmoSlot = true, will enable players to put any items on ammo slot, more used in custom shopping system -- NOTE: startStreakLevel will make a reward streak level for new players who never logged in -- NOTE: if showLootsInBestiary is true, will cause all loots to be shown in the bestiary even if the player has not reached the required number of kills +-- NOTE: minTownIdToBankTransfer blocks towns less than defined from receiving money transfers stashMoving = false depotChest = 4 autoLoot = false @@ -259,6 +260,7 @@ storeInboxMaxLimit = 2000 enablePlayerPutItemInAmmoSlot = false startStreakLevel = 0 showLootsInBestiary = false +minTownIdToBankTransfer = 3 -- Teleport summon -- Set to true will never remove the summon diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp index dc3271daaf9..4abf29c04cb 100644 --- a/src/config/config_enums.hpp +++ b/src/config/config_enums.hpp @@ -36,10 +36,10 @@ enum ConfigKey_t : uint16_t { CLASSIC_ATTACK_SPEED, CLEAN_PROTECTION_ZONES, COMBAT_CHAIN_DELAY, - COMBAT_CHAIN_TARGETS, COMBAT_CHAIN_SKILL_FORMULA_AXE, COMBAT_CHAIN_SKILL_FORMULA_CLUB, COMBAT_CHAIN_SKILL_FORMULA_SWORD, + COMBAT_CHAIN_TARGETS, COMPRESSION_LEVEL, CONVERT_UNSAFE_SCRIPTS, CORE_DIRECTORY, @@ -155,6 +155,7 @@ enum ConfigKey_t : uint16_t { METRICS_PROMETHEUS_ADDRESS, MIN_DELAY_BETWEEN_CONDITIONS, MIN_ELEMENTAL_RESISTANCE, + MIN_TOWN_ID_TO_BANK_TRANSFER, MOMENTUM_CHANCE_FORMULA_A, MOMENTUM_CHANCE_FORMULA_B, MOMENTUM_CHANCE_FORMULA_C, diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index ac78a2bbcfb..8d4ba7a77da 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -166,6 +166,9 @@ bool ConfigManager::load() { loadBoolConfig(L, XP_DISPLAY_MODE, "experienceDisplayRates", true); loadFloatConfig(L, BESTIARY_RATE_CHARM_SHOP_PRICE, "bestiaryRateCharmShopPrice", 1.0); + loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_AXE, "combatChainSkillFormulaAxe", 0.9); + loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_CLUB, "combatChainSkillFormulaClub", 0.7); + loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_SWORD, "combatChainSkillFormulaSword", 1.1); loadFloatConfig(L, FORGE_AMOUNT_MULTIPLIER, "forgeAmountMultiplier", 3.0); loadFloatConfig(L, HAZARD_EXP_BONUS_MULTIPLIER, "hazardExpBonusMultiplier", 2.0); loadFloatConfig(L, LOYALTY_BONUS_PERCENTAGE_MULTIPLIER, "loyaltyBonusPercentageMultiplier", 1.0); @@ -218,9 +221,6 @@ bool ConfigManager::load() { loadIntConfig(L, CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES, "checkExpiredMarketOffersEachMinutes", 60); loadIntConfig(L, COMBAT_CHAIN_DELAY, "combatChainDelay", 50); loadIntConfig(L, COMBAT_CHAIN_TARGETS, "combatChainTargets", 5); - loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_AXE, "combatChainSkillFormulaAxe", 0.9); - loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_CLUB, "combatChainSkillFormulaClub", 0.7); - loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_SWORD, "combatChainSkillFormulaSword", 1.1); loadIntConfig(L, COMPRESSION_LEVEL, "packetCompressionLevel", 6); loadIntConfig(L, CRITICALCHANCE, "criticalChance", 10); loadIntConfig(L, DAY_KILLS_TO_RED, "dayKillsToRedSkull", 3); @@ -287,6 +287,7 @@ bool ConfigManager::load() { loadIntConfig(L, METRICS_OSTREAM_INTERVAL, "metricsOstreamInterval", 1000); loadIntConfig(L, MIN_DELAY_BETWEEN_CONDITIONS, "minDelayBetweenConditions", 0); loadIntConfig(L, MIN_ELEMENTAL_RESISTANCE, "minElementalResistance", -200); + loadIntConfig(L, MIN_TOWN_ID_TO_BANK_TRANSFER, "minTownIdToBankTransfer", 3); loadIntConfig(L, MONTH_KILLS_TO_RED, "monthKillsToRedSkull", 10); loadIntConfig(L, MULTIPLIER_ATTACKONFIST, "multiplierSpeedOnFist", 5); loadIntConfig(L, ORANGE_SKULL_DURATION, "orangeSkullDuration", 7); diff --git a/src/game/bank/bank.cpp b/src/game/bank/bank.cpp index 30345e0495b..d9a056396ce 100644 --- a/src/game/bank/bank.cpp +++ b/src/game/bank/bank.cpp @@ -80,18 +80,18 @@ const std::set deniedNames = { "paladinsample" }; -const uint32_t minTownId = 3; - bool Bank::transferTo(const std::shared_ptr destination, uint64_t amount) { if (!destination) { g_logger().error("Bank::transferTo: destination is nullptr"); return false; } + auto bankable = getBankable(); if (!bankable) { g_logger().error("Bank::transferTo: bankable is nullptr"); return false; } + auto destinationBankable = destination->getBankable(); if (!destinationBankable) { g_logger().error("Bank::transferTo: destinationBankable is nullptr"); @@ -102,11 +102,13 @@ bool Bank::transferTo(const std::shared_ptr destination, uint64_t amount) if (destinationPlayer != nullptr) { auto name = asLowerCaseString(destinationPlayer->getName()); replaceString(name, " ", ""); + if (deniedNames.contains(name)) { g_logger().warn("Bank::transferTo: denied name: {}", name); return false; } - if (destinationPlayer->getTown()->getID() < minTownId) { + + if (destinationPlayer->getTown()->getID() < g_configManager().getNumber(MIN_TOWN_ID_TO_BANK_TRANSFER, __FUNCTION__)) { g_logger().warn("Bank::transferTo: denied town: {}", destinationPlayer->getTown()->getID()); return false; } From fceeac126c47d9e8628f40f0fe9ba0409a6c478b Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 18 Apr 2024 09:36:45 -0300 Subject: [PATCH 21/21] fix: offline training messages types and speed (#2548) --- data/scripts/creaturescripts/player/offline_training.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/scripts/creaturescripts/player/offline_training.lua b/data/scripts/creaturescripts/player/offline_training.lua index abfb0b94b3d..4466c6ee0e3 100644 --- a/data/scripts/creaturescripts/player/offline_training.lua +++ b/data/scripts/creaturescripts/player/offline_training.lua @@ -12,7 +12,7 @@ function offlineTraining.onLogin(player) player:setOfflineTrainingSkill(SKILL_NONE) if offlineTime < 600 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You must be logged out for more than 10 minutes to start offline training.") + player:sendTextMessage(MESSAGE_OFFLINE_TRAINING, "You must be logged out for more than 10 minutes to start offline training.") return true end @@ -50,15 +50,15 @@ function offlineTraining.onLogin(player) end text = string.format("%s.", text) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, text) + player:sendTextMessage(MESSAGE_OFFLINE_TRAINING, text) local vocation = player:getVocation() local promotion = vocation:getPromotion() local topVocation = not promotion and vocation or promotion - local updateSkills = false + if table.contains({ SKILL_CLUB, SKILL_SWORD, SKILL_AXE, SKILL_DISTANCE }, offlineTrainingSkill) then - local modifier = topVocation:getBaseAttackSpeed() / 1000 + local modifier = topVocation:getBaseAttackSpeed() / 1000 / configManager.getFloat(configKeys.RATE_OFFLINE_TRAINING_SPEED) updateSkills = player:addOfflineTrainingTries(offlineTrainingSkill, (trainingTime / modifier) / (offlineTrainingSkill == SKILL_DISTANCE and 4 or 2)) elseif offlineTrainingSkill == SKILL_MAGLEVEL then local gainTicks = topVocation:getManaGainTicks() * 2