diff --git a/data/sql/updates/pending_db_world/rev_1646287552186744609.sql b/data/sql/updates/pending_db_world/rev_1646287552186744609.sql new file mode 100644 index 000000000..9e8d68436 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1646287552186744609.sql @@ -0,0 +1,5 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1646287552186744609'); + +DELETE FROM `command` WHERE `name`='debug objectcount'; +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('debug objectcount',3,'Syntax: .debug objectcount Shows the number of Creatures and GameObjects for the specified map id or for all maps if none is specified'); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index ca0127439..dbee10fc3 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -635,6 +635,11 @@ public: _updateObjects.erase(obj); } + size_t GetActiveNonPlayersCount() const + { + return m_activeNonPlayers.size(); + } + private: void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index b45c949a2..9e159fbd8 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -103,6 +103,7 @@ public: { "los", HandleDebugLoSCommand, SEC_ADMINISTRATOR, Console::No }, { "moveflags", HandleDebugMoveflagsCommand, SEC_ADMINISTRATOR, Console::No }, { "unitstate", HandleDebugUnitStateCommand, SEC_ADMINISTRATOR, Console::No }, + { "objectcount", HandleDebugObjectCountCommand, SEC_ADMINISTRATOR, Console::Yes}, { "dummy", HandleDebugDummyCommand, SEC_ADMINISTRATOR, Console::No } }; static ChatCommandTable commandTable = @@ -1244,6 +1245,84 @@ public: return true; } + static bool HandleDebugObjectCountCommand(ChatHandler* handler, Optional mapId) + { + if (mapId) + { + sMapMgr->DoForAllMapsWithMapId(mapId.value(), + [handler](Map* map) -> void + { + HandleDebugObjectCountMap(handler, map); + } + ); + } + else + { + sMapMgr->DoForAllMaps( + [handler](Map* map) -> void + { + HandleDebugObjectCountMap(handler, map); + } + ); + } + + return true; + } + + class CreatureCountWorker + { + public: + CreatureCountWorker() { } + + void Visit(std::unordered_map& creatureMap) + { + for (auto const& p : creatureMap) + { + uint32& count = creatureIds[p.second->GetEntry()]; + ++count; + } + } + + template + void Visit(std::unordered_map&) { } + + std::vector> GetTopCreatureCount(uint32 count) + { + auto comp = [](std::pair const& a, std::pair const& b) + { + return a.second > b.second; + }; + std::set, decltype(comp)> set(creatureIds.begin(), creatureIds.end(), comp); + + count = std::min(count, uint32(set.size())); + std::vector> result(count); + std::copy_n(set.begin(), count, result.begin()); + + return result; + } + + private: + std::unordered_map creatureIds; + }; + + static void HandleDebugObjectCountMap(ChatHandler* handler, Map* map) + { + handler->PSendSysMessage("Map Id: %u Name: '%s' Instance Id: %u Creatures: %u GameObjects: %u SetActive Objects: %u", + map->GetId(), map->GetMapName(), map->GetInstanceId(), + uint64(map->GetObjectsStore().Size()), + uint64(map->GetObjectsStore().Size()), + uint64(map->GetActiveNonPlayersCount())); + + CreatureCountWorker worker; + TypeContainerVisitor visitor(worker); + visitor.Visit(map->GetObjectsStore()); + + handler->PSendSysMessage("Top Creatures count:"); + + for (auto&& p : worker.GetTopCreatureCount(5)) + handler->PSendSysMessage("Entry: %u Count: %u", p.first, p.second); + } + static bool HandleDebugDummyCommand(ChatHandler* handler) { handler->SendSysMessage("This command does nothing right now. Edit your local core (cs_debug.cpp) to make it do whatever you need for testing.");