diff --git a/data/sql/updates/pending_db_world/rev_1635920288146483276.sql b/data/sql/updates/pending_db_world/rev_1635920288146483276.sql new file mode 100644 index 000000000..0db8e9e99 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1635920288146483276.sql @@ -0,0 +1,3 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1635920288146483276'); + +DELETE FROM `command` WHERE `name`='list gobject'; diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index a8a1cef9f..b381cc591 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -22,16 +22,20 @@ Comment: All list related commands Category: commandscripts EndScriptData */ +#include "ScriptMgr.h" #include "Chat.h" +#include "Creature.h" +#include "DatabaseEnv.h" +#include "DBCStores.h" +#include "GameObject.h" #include "Language.h" +#include "MapMgr.h" +#include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" -#include "ScriptMgr.h" +#include "Random.h" #include "SpellAuraEffects.h" - -#if AC_COMPILER == AC_COMPILER_GNU -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +#include "WorldSession.h" using namespace Acore::ChatCommands; @@ -42,49 +46,38 @@ public: ChatCommandTable GetCommands() const override { + static ChatCommandTable listAurasCommandTable = + { + { "", HandleListAllAurasCommand, SEC_MODERATOR, Console::No }, + { "id", HandleListAurasByIdCommand, SEC_MODERATOR, Console::No }, + { "name", HandleListAurasByNameCommand, SEC_MODERATOR, Console::No }, + }; + static ChatCommandTable listCommandTable = { - { "creature", SEC_MODERATOR, true, &HandleListCreatureCommand, "" }, - { "item", SEC_MODERATOR, true, &HandleListItemCommand, "" }, - { "object", SEC_MODERATOR, true, &HandleListObjectCommand, "" }, - { "gobject", SEC_MODERATOR, true, &HandleListObjectCommand, "" }, - { "auras", SEC_MODERATOR, false, &HandleListAurasCommand, "" } + { "creature", HandleListCreatureCommand, SEC_MODERATOR, Console::Yes }, + { "item", HandleListItemCommand, SEC_MODERATOR, Console::Yes }, + { "object", HandleListObjectCommand, SEC_MODERATOR, Console::Yes }, + { "auras", listAurasCommandTable }, }; static ChatCommandTable commandTable = { - { "list", SEC_MODERATOR, true, nullptr, "", listCommandTable } + { "list", listCommandTable } }; return commandTable; } - static bool HandleListCreatureCommand(ChatHandler* handler, char const* args) + static bool HandleListCreatureCommand(ChatHandler* handler, Variant, uint32> creatureId, Optional countArg) { - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r - char* id = handler->extractKeyFromLink((char*)args, "Hcreature_entry"); - if (!id) - return false; - - uint32 creatureId = atol(id); - if (!creatureId) - { - handler->PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, creatureId); - handler->SetSentErrorMessage(true); - return false; - } - CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creatureId); if (!cInfo) { - handler->PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, creatureId); + handler->PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, uint32(creatureId)); handler->SetSentErrorMessage(true); return false; } - char* countStr = strtok(nullptr, " "); - uint32 count = countStr ? atol(countStr) : 10; + uint32 count = countArg.value_or(10); if (count == 0) return false; @@ -92,7 +85,7 @@ public: QueryResult result; uint32 creatureCount = 0; - result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'", creatureId); + result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'", uint32(creatureId)); if (result) creatureCount = (*result)[0].GetUInt64(); @@ -100,11 +93,11 @@ public: { Player* player = handler->GetSession()->GetPlayer(); result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM creature WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", - player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), creatureId, count); + player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), uint32(creatureId), count); } else result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM creature WHERE id = '%u' LIMIT %u", - creatureId, count); + uint32(creatureId), count); if (result) { @@ -116,48 +109,64 @@ public: float y = fields[2].GetFloat(); float z = fields[3].GetFloat(); uint16 mapId = fields[4].GetUInt16(); + bool liveFound = false; + // Get map (only support base map from console) + Map* thisMap; if (handler->GetSession()) - handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapId); + thisMap = handler->GetSession()->GetPlayer()->GetMap(); else - handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name.c_str(), x, y, z, mapId); - } while (result->NextRow()); + thisMap = sMapMgr->FindBaseNonInstanceMap(mapId); + + // If map found, try to find active version of this creature + if (thisMap) + { + auto const creBounds = thisMap->GetCreatureBySpawnIdStore().equal_range(guid); + if (creBounds.first != creBounds.second) + { + for (std::unordered_multimap::const_iterator itr = creBounds.first; itr != creBounds.second;) + { + if (handler->GetSession()) + handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->IsAlive() ? "*" : " "); + else + handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->IsAlive() ? "*" : " "); + ++itr; + } + liveFound = true; + } + } + + if (!liveFound) + { + if (handler->GetSession()) + handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapId, "", ""); + else + handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name.c_str(), x, y, z, mapId, "", ""); + } + } + while (result->NextRow()); } - handler->PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE, creatureId, creatureCount); + handler->PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE, uint32(creatureId), creatureCount); return true; } - static bool HandleListItemCommand(ChatHandler* handler, char const* args) + static bool HandleListItemCommand(ChatHandler* handler, Variant, uint32> itemArg, Optional countArg) { - if (!*args) - return false; + uint32 itemId = 0; + uint32 count = countArg.value_or(10); - char* id = handler->extractKeyFromLink((char*)args, "Hitem"); - if (!id) - return false; - - uint32 itemId = atol(id); - if (!itemId) + if (itemArg.holds_alternative>()) { - handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); - handler->SetSentErrorMessage(true); - return false; + itemId = itemArg.get>()->Item->ItemId; + } + else + { + itemId = itemArg.get(); } - ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId); - if (!itemTemplate) - { - handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); - handler->SetSentErrorMessage(true); - return false; - } - - char* countStr = strtok(nullptr, " "); - uint32 count = countStr ? atol(countStr) : 10; - - if (count == 0) + if (!count || !itemId) return false; PreparedQueryResult result; @@ -189,7 +198,7 @@ public: uint32 ownerAccountId = fields[4].GetUInt32(); std::string ownerName = fields[5].GetString(); - char const* itemPos = 0; + char const* itemPos = nullptr; if (Player::IsEquipmentPos(itemBag, itemSlot)) itemPos = "[equipped]"; else if (Player::IsInventoryPos(itemBag, itemSlot)) @@ -200,13 +209,14 @@ public: itemPos = ""; handler->PSendSysMessage(LANG_ITEMLIST_SLOT, itemGuid, ownerName.c_str(), ownerGuid, ownerAccountId, itemPos); - } while (result->NextRow()); + } + while (result->NextRow()); uint32 resultCount = uint32(result->GetRowCount()); if (count > resultCount) count -= resultCount; - else if (count) + else count = 0; } @@ -235,8 +245,8 @@ public: do { Field* fields = result->Fetch(); - uint32 itemGuid = fields[0].GetUInt32(); - uint32 itemSender = fields[1].GetUInt32(); + ObjectGuid::LowType itemGuid = fields[0].GetUInt32(); + ObjectGuid::LowType itemSender = fields[1].GetUInt32(); uint32 itemReceiver = fields[2].GetUInt32(); uint32 itemSenderAccountId = fields[3].GetUInt32(); std::string itemSenderName = fields[4].GetString(); @@ -246,13 +256,14 @@ public: char const* itemPos = "[in mail]"; handler->PSendSysMessage(LANG_ITEMLIST_MAIL, itemGuid, itemSenderName.c_str(), itemSender, itemSenderAccountId, itemReceiverName.c_str(), itemReceiver, itemReceiverAccount, itemPos); - } while (result->NextRow()); + } + while (result->NextRow()); uint32 resultCount = uint32(result->GetRowCount()); if (count > resultCount) count -= resultCount; - else if (count) + else count = 0; } @@ -289,7 +300,8 @@ public: char const* itemPos = "[in auction]"; handler->PSendSysMessage(LANG_ITEMLIST_AUCTION, itemGuid, ownerName.c_str(), owner, ownerAccountId, itemPos); - } while (result->NextRow()); + } + while (result->NextRow()); } // guild bank case @@ -319,13 +331,14 @@ public: char const* itemPos = "[in guild bank]"; handler->PSendSysMessage(LANG_ITEMLIST_GUILD, itemGuid, guildName.c_str(), guildGuid, itemPos); - } while (result->NextRow()); + } + while (result->NextRow()); uint32 resultCount = uint32(result->GetRowCount()); if (count > resultCount) count -= resultCount; - else if (count) + else count = 0; } @@ -341,34 +354,17 @@ public: return true; } - static bool HandleListObjectCommand(ChatHandler* handler, char const* args) + static bool HandleListObjectCommand(ChatHandler* handler, Variant, uint32> gameObjectId, Optional countArg) { - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r - char* id = handler->extractKeyFromLink((char*)args, "Hgameobject_entry"); - if (!id) - return false; - - uint32 gameObjectId = atol(id); - if (!gameObjectId) - { - handler->PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, gameObjectId); - handler->SetSentErrorMessage(true); - return false; - } - GameObjectTemplate const* gInfo = sObjectMgr->GetGameObjectTemplate(gameObjectId); if (!gInfo) { - handler->PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, gameObjectId); + handler->PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, uint32(gameObjectId)); handler->SetSentErrorMessage(true); return false; } - char* countStr = strtok(nullptr, " "); - uint32 count = countStr ? atol(countStr) : 10; + uint32 count = countArg.value_or(10); if (count == 0) return false; @@ -376,7 +372,7 @@ public: QueryResult result; uint32 objectCount = 0; - result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'", gameObjectId); + result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'", uint32(gameObjectId)); if (result) objectCount = (*result)[0].GetUInt64(); @@ -384,11 +380,11 @@ public: { Player* player = handler->GetSession()->GetPlayer(); result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, id, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", - player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), gameObjectId, count); + player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), uint32(gameObjectId), count); } else result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, id FROM gameobject WHERE id = '%u' LIMIT %u", - gameObjectId, count); + uint32(gameObjectId), count); if (result) { @@ -401,20 +397,65 @@ public: float z = fields[3].GetFloat(); uint16 mapId = fields[4].GetUInt16(); uint32 entry = fields[5].GetUInt32(); + bool liveFound = false; + // Get map (only support base map from console) + Map* thisMap; if (handler->GetSession()) - handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapId); + thisMap = handler->GetSession()->GetPlayer()->GetMap(); else - handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name.c_str(), x, y, z, mapId); - } while (result->NextRow()); + thisMap = sMapMgr->FindBaseNonInstanceMap(mapId); + + // If map found, try to find active version of this object + if (thisMap) + { + auto const goBounds = thisMap->GetGameObjectBySpawnIdStore().equal_range(guid); + if (goBounds.first != goBounds.second) + { + for (std::unordered_multimap::const_iterator itr = goBounds.first; itr != goBounds.second;) + { + if (handler->GetSession()) + handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->isSpawned() ? "*" : " "); + else + handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->isSpawned() ? "*" : " "); + ++itr; + } + liveFound = true; + } + } + + if (!liveFound) + { + if (handler->GetSession()) + handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapId, "", ""); + else + handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name.c_str(), x, y, z, mapId, "", ""); + } + } + while (result->NextRow()); } - handler->PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE, gameObjectId, objectCount); + handler->PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE, uint32(gameObjectId), objectCount); return true; } - static bool HandleListAurasCommand(ChatHandler* handler, char const* args) + static bool HandleListAllAurasCommand(ChatHandler* handler) + { + return ListAurasCommand(handler, {}, {}); + } + + static bool HandleListAurasByIdCommand(ChatHandler* handler, uint32 spellId) + { + return ListAurasCommand(handler, spellId, {}); + } + + static bool HandleListAurasByNameCommand(ChatHandler* handler, WTail namePart) + { + return ListAurasCommand(handler, {}, namePart); + } + + static bool ListAurasCommand(ChatHandler* handler, Optional spellId, std::wstring namePart) { Unit* unit = handler->getSelectedUnit(); if (!unit) @@ -424,19 +465,23 @@ public: return false; } + wstrToLower(namePart); + char const* talentStr = handler->GetAcoreString(LANG_TALENT); char const* passiveStr = handler->GetAcoreString(LANG_PASSIVE); Unit::AuraApplicationMap const& auras = unit->GetAppliedAuras(); handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, auras.size()); - for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + for (auto const& [aurId, aurApp] : auras) { - bool talent = GetTalentSpellCost(itr->second->GetBase()->GetId()) > 0; + bool talent = GetTalentSpellCost(aurApp->GetBase()->GetId()) > 0; - AuraApplication const* aurApp = itr->second; Aura const* aura = aurApp->GetBase(); char const* name = aura->GetSpellInfo()->SpellName[handler->GetSessionDbcLocale()]; + if (!ShouldListAura(aura->GetSpellInfo(), spellId, namePart, handler->GetSessionDbcLocale())) + continue; + std::ostringstream ss_name; ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r"; @@ -447,19 +492,41 @@ public: aura->GetCasterGUID().GetCounter()); } - if (!args || std::string(args) != "all") - return true; - for (uint16 i = 0; i < TOTAL_AURAS; ++i) { Unit::AuraEffectList const& auraList = unit->GetAuraEffectsByType(AuraType(i)); if (auraList.empty()) continue; - handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, auraList.size(), i); + bool sizeLogged = false; - for (Unit::AuraEffectList::const_iterator itr = auraList.begin(); itr != auraList.end(); ++itr) - handler->PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), (*itr)->GetAmount()); + for (AuraEffect const* effect : auraList) + { + if (!ShouldListAura(effect->GetSpellInfo(), spellId, namePart, handler->GetSessionDbcLocale())) + continue; + + if (!sizeLogged) + { + sizeLogged = true; + handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, auraList.size(), i); + } + + handler->PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, effect->GetId(), effect->GetEffIndex(), effect->GetAmount()); + } + } + + return true; + } + + static bool ShouldListAura(SpellInfo const* spellInfo, Optional spellId, std::wstring namePart, uint8 locale) + { + if (spellId) + return spellInfo->Id == spellId; + + if (!namePart.empty()) + { + std::string name = spellInfo->SpellName[locale]; + return Utf8FitTo(name, namePart); } return true;