From 503735c540d5885e8b36d8cd5e7dba95f9bf6c9e Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 24 May 2026 18:32:35 -0300 Subject: [PATCH] feat(Core/Commands): add .pet rename command (#25951) Co-authored-by: Claude Opus 4.7 (1M context) --- .../rev_1779639149576950000.sql | 8 ++ .../rev_1779639149576950000.sql | 5 ++ src/server/game/Accounts/RBAC.h | 1 + src/server/game/Miscellaneous/Language.h | 6 +- src/server/scripts/Commands/cs_pet.cpp | 76 +++++++++++++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 data/sql/updates/pending_db_auth/rev_1779639149576950000.sql create mode 100644 data/sql/updates/pending_db_world/rev_1779639149576950000.sql diff --git a/data/sql/updates/pending_db_auth/rev_1779639149576950000.sql b/data/sql/updates/pending_db_auth/rev_1779639149576950000.sql new file mode 100644 index 0000000000..6d512f78cd --- /dev/null +++ b/data/sql/updates/pending_db_auth/rev_1779639149576950000.sql @@ -0,0 +1,8 @@ +-- RBAC permission for .pet rename (sec 3+, Admin role 196). +DELETE FROM `rbac_permissions` WHERE `id` = 922; +INSERT INTO `rbac_permissions` (`id`, `name`) VALUES +(922, 'Command: pet rename'); + +DELETE FROM `rbac_linked_permissions` WHERE `linkedId` = 922; +INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES +(196, 922); diff --git a/data/sql/updates/pending_db_world/rev_1779639149576950000.sql b/data/sql/updates/pending_db_world/rev_1779639149576950000.sql new file mode 100644 index 0000000000..04670b9b3e --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1779639149576950000.sql @@ -0,0 +1,5 @@ +-- acore_string entries for .pet rename command. +DELETE FROM `acore_string` WHERE `entry` IN (35453, 35454); +INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES +(35453, 'Invalid pet name: {}.', '잘못된 펫 이름입니다: {}.', 'Nom de familier invalide : {}.', 'Ungültiger Begleitername: {}.', '无效的宠物名称: {}。', '無效的寵物名稱:{}。', 'Nombre de mascota no válido: {}.', 'Nombre de mascota no válido: {}.', 'Недопустимое имя питомца: {}.'), +(35454, 'Renamed pet {0} ({1} -> {2}) for player {3} ({4}).', '플레이어 {3} ({4})의 펫 {0}의 이름을 {1}에서 {2}(으)로 변경했습니다.', 'Familier {0} renommé ({1} -> {2}) pour le joueur {3} ({4}).', 'Begleiter {0} umbenannt ({1} -> {2}) für Spieler {3} ({4}).', '已将玩家 {3} ({4}) 的宠物 {0} 重命名 ({1} -> {2})。', '已將玩家 {3} ({4}) 的寵物 {0} 重新命名({1} -> {2})。', 'Mascota {0} renombrada ({1} -> {2}) para el jugador {3} ({4}).', 'Mascota {0} renombrada ({1} -> {2}) para el jugador {3} ({4}).', 'Питомец {0} переименован ({1} -> {2}) у игрока {3} ({4}).'); diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 26cd4c3c6c..076c1e5d94 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -683,6 +683,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_RESPAWN_GAMEOBJECT_ENTRY = 919, RBAC_PERM_COMMAND_DEBUG_INFO = 920, RBAC_PERM_COMMAND_DEBUG_COSMETIC = 921, + RBAC_PERM_COMMAND_PET_RENAME = 922, // custom permissions 1000+ RBAC_PERM_MAX }; diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index c4ac6dbdb5..9067bff5c3 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1508,6 +1508,10 @@ enum AcoreStrings LANG_RESPAWN_ENTRY_GAMEOBJECT_QUEUED = 35452, // List respawns console support - LANG_LIST_RESPAWNS_NO_MAP = 35447 + LANG_LIST_RESPAWNS_NO_MAP = 35447, + + // Pet rename command + LANG_PET_RENAME_INVALID = 35453, + LANG_PET_RENAME_SUCCESS = 35454 }; #endif diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp index ed46d29823..a4e3df8961 100644 --- a/src/server/scripts/Commands/cs_pet.cpp +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -19,6 +19,8 @@ #include "CommandScript.h" #include "DatabaseEnv.h" #include +#include "GameTime.h" +#include "Group.h" #include "Language.h" #include "Log.h" #include "ObjectMgr.h" @@ -43,6 +45,7 @@ public: { "delete", HandlePetDeleteCommand, rbac::RBAC_PERM_COMMAND_PET_DELETE, Console::Yes }, { "learn", HandlePetLearnCommand, rbac::RBAC_PERM_COMMAND_PET_LEARN, Console::No }, { "list", HandlePetListCommand, rbac::RBAC_PERM_COMMAND_PET_LIST, Console::Yes }, + { "rename", HandlePetRenameCommand, rbac::RBAC_PERM_COMMAND_PET_RENAME, Console::Yes }, { "unlearn", HandlePetUnlearnCommand, rbac::RBAC_PERM_COMMAND_PET_UNLEARN, Console::No } }; @@ -227,6 +230,79 @@ public: return true; } + static bool HandlePetRenameCommand(ChatHandler* handler, PlayerIdentifier owner, uint32 petNumber, std::string newName) + { + if (ObjectMgr::CheckPetName(newName) != PET_NAME_SUCCESS) + { + handler->SendErrorMessage(LANG_PET_RENAME_INVALID, newName); + return false; + } + + ObjectGuid ownerGuid = owner.GetGUID(); + + QueryResult result = CharacterDatabase.Query("SELECT name FROM character_pet WHERE id = {} AND owner = {}", petNumber, ownerGuid.GetCounter()); + + if (!result) + { + handler->SendErrorMessage(LANG_PET_DELETE_NOT_FOUND, petNumber, owner.GetName(), ownerGuid.GetCounter()); + return false; + } + + std::string oldName = result->Fetch()[0].Get(); + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_NAME); + stmt->SetData(0, newName); + stmt->SetData(1, ownerGuid.GetCounter()); + stmt->SetData(2, petNumber); + CharacterDatabase.Execute(stmt); + + if (Player* online = owner.GetConnectedPlayer()) + { + if (Pet* activePet = online->GetPet()) + { + if (activePet->GetCharmInfo() && activePet->GetCharmInfo()->GetPetNumber() == petNumber) + { + activePet->SetName(newName); + // Bump the name timestamp so nearby clients re-query and drop their cached pet name. + activePet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(GameTime::GetGameTime().count())); + activePet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); + if (online->GetGroup()) + online->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); + } + } + + if (PetStable* stable = online->GetPetStable()) + { + if (stable->CurrentPet && stable->CurrentPet->PetNumber == petNumber) + { + stable->CurrentPet->Name = newName; + stable->CurrentPet->WasRenamed = true; + } + + for (Optional& stabled : stable->StabledPets) + { + if (stabled && stabled->PetNumber == petNumber) + { + stabled->Name = newName; + stabled->WasRenamed = true; + } + } + + for (PetStable::PetInfo& unslotted : stable->UnslottedPets) + { + if (unslotted.PetNumber == petNumber) + { + unslotted.Name = newName; + unslotted.WasRenamed = true; + } + } + } + } + + handler->PSendSysMessage(LANG_PET_RENAME_SUCCESS, petNumber, oldName, newName, owner.GetName(), ownerGuid.GetCounter()); + return true; + } + static bool HandlePetUnlearnCommand(ChatHandler* handler, SpellInfo const* spell) { if (!spell)