diff --git a/data/sql/updates/pending_db_world/rev_1622479207694702700.sql b/data/sql/updates/pending_db_world/rev_1622479207694702700.sql new file mode 100644 index 000000000..d61405fa0 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1622479207694702700.sql @@ -0,0 +1,3 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1622479207694702700'); + +UPDATE `command` SET `help` = 'Syntax: .character rename [$name] [reserveName]\r\n\r\nMark the character (selected in-game or with the $name argument) for rename at next login.\r\n\r\nIf [reserveName] is 1 then the player''s current name is added to the list of reserved names.' WHERE `command`.`name` = 'character rename'; diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 854a6c3f0..f5e26f606 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -574,4 +574,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() // Recovery Item PrepareStatement(CHAR_INS_RECOVERY_ITEM, "INSERT INTO recovery_item (Guid, ItemEntry, Count) VALUES (?, ?, ?)", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_RECOVERY_ITEM, "DELETE FROM recovery_item WHERE Guid = ? AND ItemEntry = ? AND Count = ? ORDER BY Id DESC LIMIT 1", CONNECTION_ASYNC); + + // Character names + PrepareStatement(CHAR_INS_RESERVED_PLAYER_NAME, "INSERT IGNORE INTO reserved_name (name) VALUES (?)", CONNECTION_ASYNC); } diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index ebf4a0909..dab93381c 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -507,6 +507,8 @@ enum CharacterDatabaseStatements CHAR_INS_RECOVERY_ITEM, CHAR_DEL_RECOVERY_ITEM, + CHAR_INS_RESERVED_PLAYER_NAME, + MAX_CHARACTERDATABASE_STATEMENTS }; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 24e466ada..ea363bed0 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7553,6 +7553,26 @@ bool ObjectMgr::IsReservedName(const std::string& name) const return _reservedNamesStore.find(wstr) != _reservedNamesStore.end(); } +void ObjectMgr::AddReservedPlayerName(std::string const& name) +{ + if (!IsReservedName(name)) + { + std::wstring wstr; + if (!Utf8toWStr(name, wstr)) + { + LOG_ERROR("server", "Could not add invalid name to reserved player names: %s", name.c_str()); + return; + } + wstrToLower(wstr); + + _reservedNamesStore.insert(wstr); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_RESERVED_PLAYER_NAME); + stmt->setString(0, name); + CharacterDatabase.Execute(stmt); + } +} + enum LanguageType { LT_BASIC_LATIN = 0x0000, diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 0daad63c1..879f37fc2 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1255,6 +1255,7 @@ public: // reserved names void LoadReservedPlayersNames(); [[nodiscard]] bool IsReservedName(std::string const& name) const; + void AddReservedPlayerName(std::string const& name); // name with valid structure and symbols static uint8 CheckPlayerName(std::string const& name, bool create = false); diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index c2a9667bb..ba523d1cd 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -302,10 +302,20 @@ public: //rename characters static bool HandleCharacterRenameCommand(ChatHandler* handler, char const* args) { + char* nameStr = strtok((char*)args, " "); + char* reserveNameStr = strtok(nullptr, " "); + + if (!reserveNameStr && nameStr && atoi(nameStr) == 1) + { + reserveNameStr = nameStr; + nameStr = nullptr; + } + bool reserveName = reserveNameStr != nullptr && atoi(reserveNameStr) == 1; + Player* target; ObjectGuid targetGuid; std::string targetName; - if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) + if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &targetName)) return false; if (target) @@ -332,6 +342,11 @@ public: CharacterDatabase.Execute(stmt); } + if (reserveName) + { + sObjectMgr->AddReservedPlayerName(targetName); + } + return true; }