@@ -424,15 +424,15 @@ Game &Game::getInstance() {
424424}
425425
426426void Game::resetMonsters () const {
427- for (const auto &[monsterId, monster] : getMonsters ()) {
427+ for (const auto &monster : getMonsters ()) {
428428 monster->clearTargetList ();
429429 monster->clearFriendList ();
430430 }
431431}
432432
433433void Game::resetNpcs () const {
434434 // Close shop window from all npcs and reset the shopPlayerSet
435- for (const auto &[npcId, npc] : getNpcs ()) {
435+ for (const auto &npc : getNpcs ()) {
436436 npc->closeAllShopWindows ();
437437 npc->resetPlayerInteractions ();
438438 }
@@ -954,23 +954,29 @@ std::shared_ptr<Monster> Game::getMonsterByID(uint32_t id) {
954954 return nullptr ;
955955 }
956956
957- auto it = monsters .find (id);
958- if (it == monsters .end ()) {
957+ auto it = monstersIdIndex .find (id);
958+ if (it == monstersIdIndex .end ()) {
959959 return nullptr ;
960960 }
961- return it->second ;
961+
962+ if (it->second >= monsters.size ()) {
963+ return nullptr ;
964+ }
965+
966+ return monsters[it->second ];
962967}
963968
964969std::shared_ptr<Npc> Game::getNpcByID (uint32_t id) {
965970 if (id == 0 ) {
966971 return nullptr ;
967972 }
968973
969- auto it = npcs .find (id);
970- if (it == npcs .end ()) {
974+ auto it = npcsIdIndex .find (id);
975+ if (it == npcsIdIndex .end ()) {
971976 return nullptr ;
972977 }
973- return it->second ;
978+
979+ return npcs[it->second ];
974980}
975981
976982std::shared_ptr<Player> Game::getPlayerByID (uint32_t id, bool allowOffline /* = false */ ) {
@@ -990,43 +996,41 @@ std::shared_ptr<Player> Game::getPlayerByID(uint32_t id, bool allowOffline /* =
990996 return tmpPlayer;
991997}
992998
993- std::shared_ptr<Creature> Game::getCreatureByName (const std::string &s ) {
994- if (s .empty ()) {
999+ std::shared_ptr<Creature> Game::getCreatureByName (const std::string &creatureName ) {
1000+ if (creatureName .empty ()) {
9951001 return nullptr ;
9961002 }
9971003
998- const std::string &lowerCaseName = asLowerCaseString (s );
1004+ const std::string &lowerCaseName = asLowerCaseString (creatureName );
9991005
10001006 auto m_it = mappedPlayerNames.find (lowerCaseName);
10011007 if (m_it != mappedPlayerNames.end ()) {
10021008 return m_it->second .lock ();
10031009 }
10041010
1005- for (const auto &it : npcs) {
1006- if (lowerCaseName == asLowerCaseString (it.second ->getName ())) {
1007- return it.second ;
1008- }
1011+ auto npcIterator = npcsNameIndex.find (lowerCaseName);
1012+ if (npcIterator != npcsNameIndex.end ()) {
1013+ return npcs[npcIterator->second ];
10091014 }
10101015
1011- for (const auto &it : monsters) {
1012- if (lowerCaseName == asLowerCaseString (it.second ->getName ())) {
1013- return it.second ;
1014- }
1016+ auto monsterIterator = monstersNameIndex.find (lowerCaseName);
1017+ if (monsterIterator != monstersNameIndex.end ()) {
1018+ return monsters[monsterIterator->second ];
10151019 }
10161020 return nullptr ;
10171021}
10181022
1019- std::shared_ptr<Npc> Game::getNpcByName (const std::string &s ) {
1020- if (s .empty ()) {
1023+ std::shared_ptr<Npc> Game::getNpcByName (const std::string &npcName ) {
1024+ if (npcName .empty ()) {
10211025 return nullptr ;
10221026 }
10231027
1024- const char * npcName = s.c_str ();
1025- for (const auto &it : npcs) {
1026- if (strcasecmp (npcName, it.second ->getName ().c_str ()) == 0 ) {
1027- return it.second ;
1028- }
1028+ const std::string lowerCaseName = asLowerCaseString (npcName);
1029+ auto it = npcsNameIndex.find (lowerCaseName);
1030+ if (it != npcsNameIndex.end ()) {
1031+ return npcs[it->second ];
10291032 }
1033+
10301034 return nullptr ;
10311035}
10321036
@@ -3184,13 +3188,18 @@ ReturnValue Game::internalCollectManagedItems(const std::shared_ptr<Player> &pla
31843188
31853189ReturnValue Game::collectRewardChestItems (const std::shared_ptr<Player> &player, uint32_t maxMoveItems /* = 0*/ ) {
31863190 // Check if have item on player reward chest
3187- std::shared_ptr<RewardChest> rewardChest = player->getRewardChest ();
3191+ const std::shared_ptr<RewardChest> & rewardChest = player->getRewardChest ();
31883192 if (rewardChest->empty ()) {
31893193 g_logger ().debug (" Reward chest is empty" );
31903194 return RETURNVALUE_REWARDCHESTISEMPTY;
31913195 }
31923196
3193- auto rewardItemsVector = player->getRewardsFromContainer (rewardChest->getContainer ());
3197+ const auto &container = rewardChest->getContainer ();
3198+ if (!container) {
3199+ return RETURNVALUE_REWARDCHESTISEMPTY;
3200+ }
3201+
3202+ auto rewardItemsVector = player->getRewardsFromContainer (container);
31943203 auto rewardCount = rewardItemsVector.size ();
31953204 uint32_t movedRewardItems = 0 ;
31963205 std::string lootedItemsMessage;
@@ -9931,19 +9940,72 @@ void Game::removePlayer(const std::shared_ptr<Player> &player) {
99319940}
99329941
99339942void Game::addNpc (const std::shared_ptr<Npc> &npc) {
9934- npcs[npc->getID ()] = npc;
9943+ npcs.push_back (npc);
9944+ size_t index = npcs.size () - 1 ;
9945+ npcsNameIndex[npc->getLowerName ()] = index;
9946+ npcsIdIndex[npc->getID ()] = index;
99359947}
99369948
99379949void Game::removeNpc (const std::shared_ptr<Npc> &npc) {
9938- npcs.erase (npc->getID ());
9950+ if (!npc) {
9951+ return ;
9952+ }
9953+
9954+ auto npcId = npc->getID ();
9955+ const auto &npcLowerName = npc->getLowerName ();
9956+ auto it = npcsIdIndex.find (npcId);
9957+ if (it != npcsIdIndex.end ()) {
9958+ size_t index = it->second ;
9959+ npcsNameIndex.erase (npcLowerName);
9960+ npcsIdIndex.erase (npcId);
9961+
9962+ if (index != npcs.size () - 1 ) {
9963+ std::swap (npcs[index], npcs.back ());
9964+
9965+ const auto &movedNpc = npcs[index];
9966+ npcsNameIndex[movedNpc->getLowerName ()] = index;
9967+ npcsIdIndex[movedNpc->getID ()] = index;
9968+ }
9969+
9970+ npcs.pop_back ();
9971+ }
99399972}
99409973
99419974void Game::addMonster (const std::shared_ptr<Monster> &monster) {
9942- monsters[monster->getID ()] = monster;
9975+ if (!monster) {
9976+ return ;
9977+ }
9978+
9979+ const auto &lowerName = monster->getLowerName ();
9980+ monsters.push_back (monster);
9981+ size_t index = monsters.size () - 1 ;
9982+ monstersNameIndex[lowerName] = index;
9983+ monstersIdIndex[monster->getID ()] = index;
99439984}
99449985
99459986void Game::removeMonster (const std::shared_ptr<Monster> &monster) {
9946- monsters.erase (monster->getID ());
9987+ if (!monster) {
9988+ return ;
9989+ }
9990+
9991+ auto monsterId = monster->getID ();
9992+ const auto &monsterLowerName = monster->getLowerName ();
9993+ auto it = monstersIdIndex.find (monsterId);
9994+ if (it != monstersIdIndex.end ()) {
9995+ size_t index = it->second ;
9996+ monstersNameIndex.erase (monsterLowerName);
9997+ monstersIdIndex.erase (monsterId);
9998+
9999+ if (index != monsters.size () - 1 ) {
10000+ std::swap (monsters[index], monsters.back ());
10001+
10002+ const auto &movedMonster = monsters[index];
10003+ monstersNameIndex[movedMonster->getLowerName ()] = index;
10004+ monstersIdIndex[movedMonster->getID ()] = index;
10005+ }
10006+
10007+ monsters.pop_back ();
10008+ }
994710009}
994810010
994910011std::shared_ptr<Guild> Game::getGuild (uint32_t id, bool allowOffline /* = flase */ ) const {
@@ -10152,7 +10214,7 @@ uint32_t Game::makeFiendishMonster(uint32_t forgeableMonsterId /* = 0*/, bool cr
1015210214 forgeableMonsters.clear ();
1015310215 // If the forgeable monsters haven't been created
1015410216 // Then we'll create them so they don't return in the next if (forgeableMonsters.empty())
10155- for (const auto &[monsterId, monster] : monsters) {
10217+ for (const auto &monster : monsters) {
1015610218 auto monsterTile = monster->getTile ();
1015710219 if (!monster || !monsterTile) {
1015810220 continue ;
@@ -10325,7 +10387,7 @@ void Game::updateForgeableMonsters() {
1032510387 if (auto influencedLimit = g_configManager ().getNumber (FORGE_INFLUENCED_CREATURES_LIMIT);
1032610388 forgeableMonsters.size () < influencedLimit) {
1032710389 forgeableMonsters.clear ();
10328- for (const auto &[monsterId, monster] : monsters) {
10390+ for (const auto &monster : monsters) {
1032910391 const auto &monsterTile = monster->getTile ();
1033010392 if (!monsterTile) {
1033110393 continue ;
@@ -10541,7 +10603,7 @@ void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint
1054110603 }
1054210604
1054310605 // Updates the parent of the reward chest and reward containers to avoid memory usage after cleaning
10544- auto playerRewardChest = player->getRewardChest ();
10606+ const auto & playerRewardChest = player->getRewardChest ();
1054510607 if (playerRewardChest && playerRewardChest->empty ()) {
1054610608 player->sendCancelMessage (RETURNVALUE_REWARDCHESTISEMPTY);
1054710609 return ;
0 commit comments