diff options
5 files changed, 123 insertions, 16 deletions
diff --git a/sql/updates/world/2013_04_29_00_world_misc.sql b/sql/updates/world/2013_04_29_00_world_misc.sql new file mode 100644 index 00000000000..716a77be584 --- /dev/null +++ b/sql/updates/world/2013_04_29_00_world_misc.sql @@ -0,0 +1,11 @@ +DELETE FROM `command` WHERE `name` = 'character rename'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('character rename', 2, 'Syntax: .character rename [$name] [$newName] \n\nMark selected in game or by $name in command character for rename at next login.\n\nIf $newName then the player will be forced rename.'); + +SET @ENTRY := 98; +SET @ENTRY1 := 167; +DELETE FROM `trinity_string` WHERE `entry` IN (@ENTRY, @ENTRY+1, @ENTRY1); +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(@ENTRY, '\'%s\' already exists as character name, choose another one'), +(@ENTRY+1, 'Player \'%s\' forced rename to \'%s\''), +(@ENTRY1, 'This name is reserved, choose another one'); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index e03adf2a4a1..eb55e44c9ee 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -121,7 +121,8 @@ enum TrinityStrings LANG_RBAC_LIST_PERMISSIONS_HEADER = 95, LANG_GUILD_RENAME_ALREADY_EXISTS = 96, LANG_GUILD_RENAME_DONE = 97, - // Room for more level 0 98-99 not used + LANG_RENAME_PLAYER_ALREADY_EXISTS = 98, + LANG_RENAME_PLAYER_WITH_NEW_NAME = 99, // level 1 chat LANG_GLOBAL_NOTIFY = 100, @@ -198,7 +199,7 @@ enum TrinityStrings LANG_COMMAND_TELE_NOTFOUND = 164, LANG_COMMAND_TELE_PARAMETER = 165, LANG_COMMAND_TELE_NOLOCATION = 166, - // 167 // not used + LANG_RESERVED_NAME = 167, LANG_COMMAND_TELE_LOCATION = 168, LANG_MAIL_SENT = 169, diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index c29b62975ab..fdcf88177a9 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -308,28 +308,121 @@ public: if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; - if (target) + char const* newNameStr = strtok(NULL, " "); + + if (newNameStr) { - // check online security - if (handler->HasLowerSecurity(target, 0)) + std::string playerOldName; + std::string newName = newNameStr; + + if (target) + { + // check online security + if (handler->HasLowerSecurity(target, 0)) + return false; + + playerOldName = target->GetName(); + } + else + { + // check offline security + if (handler->HasLowerSecurity(NULL, targetGuid)) + return false; + + sObjectMgr->GetPlayerNameByGUID(targetGuid, playerOldName); + } + + if (!normalizePlayerName(newName)) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + if (ObjectMgr::CheckPlayerName(newName, true) != CHAR_NAME_SUCCESS) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + if (WorldSession* session = handler->GetSession()) + { + if (!session->HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName)) + { + handler->SendSysMessage(LANG_RESERVED_NAME); + handler->SetSentErrorMessage(true); + return false; + } + } + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); + stmt->setString(0, newName); + PreparedQueryResult result = CharacterDatabase.Query(stmt); + if (result) + { + handler->PSendSysMessage(LANG_RENAME_PLAYER_ALREADY_EXISTS, newName.c_str()); + handler->SetSentErrorMessage(true); return false; + } + + // Remove declined name from db + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_DECLINED_NAME); + stmt->setUInt32(0, targetGuid); + CharacterDatabase.Execute(stmt); + + if (target) + { + target->SetName(newName); + + if (WorldSession* session = target->GetSession()) + session->KickPlayer(); + } + else + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME_BY_GUID); + stmt->setString(0, newName); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + CharacterDatabase.Execute(stmt); + } + + sWorld->UpdateCharacterNameData(targetGuid, newName); - handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_RENAME); + handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, playerOldName.c_str(), newName.c_str()); + + if (WorldSession* session = handler->GetSession()) + { + if (Player* player = session->GetPlayer()) + sLog->outCommand(session->GetAccountId(), "GM %s (Account: %u) forced rename %s to player %s (Account: %u)", player->GetName().c_str(), session->GetAccountId(), newName.c_str(), playerOldName.c_str(), sObjectMgr->GetPlayerAccountIdByGUID(targetGuid)); + } + else + sLog->outCommand(0, "CONSOLE forced rename '%s' to '%s' (GUID: %u)", playerOldName.c_str(), newName.c_str(), GUID_LOPART(targetGuid)); } else { - // check offline security - if (handler->HasLowerSecurity(NULL, targetGuid)) - return false; + if (target) + { + // check online security + if (handler->HasLowerSecurity(target, 0)) + return false; - std::string oldNameLink = handler->playerLink(targetName); - handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); + handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_RENAME); + } + else + { + // check offline security + if (handler->HasLowerSecurity(NULL, targetGuid)) + return false; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - stmt->setUInt16(0, uint16(AT_LOGIN_RENAME)); - stmt->setUInt32(1, GUID_LOPART(targetGuid)); - CharacterDatabase.Execute(stmt); + std::string oldNameLink = handler->playerLink(targetName); + handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_RENAME)); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + CharacterDatabase.Execute(stmt); + } } return true; diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index f834ead6a5b..2e6ab10b087 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -165,6 +165,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_MATCH_MAKER_RATING, "SELECT matchMakerRating FROM character_arena_stats WHERE guid = ? AND slot = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARACTER_COUNT, "SELECT account, COUNT(guid) FROM characters WHERE account = ? GROUP BY account", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_NAME, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_NAME_BY_GUID, "UPDATE characters SET name = ? WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_DECLINED_NAME, "DELETE FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC); // Guild handling diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 65878b4c577..59ac15978b6 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -161,6 +161,7 @@ enum CharacterDatabaseStatements CHAR_SEL_MATCH_MAKER_RATING, CHAR_SEL_CHARACTER_COUNT, CHAR_UPD_NAME, + CHAR_UPD_NAME_BY_GUID, CHAR_DEL_DECLINED_NAME, CHAR_SEL_CHARACTER_DATA_BY_GUID, |