TrinityCore
Loading...
Searching...
No Matches
cs_character.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/* ScriptData
19Name: character_commandscript
20%Complete: 100
21Comment: All character related commands
22Category: commandscripts
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "AccountMgr.h"
27#include "CharacterCache.h"
28#include "Chat.h"
29#include "ChatCommand.h"
30#include "DatabaseEnv.h"
31#include "DB2Stores.h"
32#include "Log.h"
33#include "ObjectMgr.h"
34#include "Player.h"
35#include "PlayerDump.h"
36#include "ReputationMgr.h"
37#include "World.h"
38#include "WorldSession.h"
39#include <sstream>
40
41using namespace Trinity::ChatCommands;
42
44{
45public:
46 character_commandscript() : CommandScript("character_commandscript") { }
47
48 std::span<ChatCommandBuilder const> GetCommands() const override
49 {
50 static ChatCommandTable pdumpCommandTable =
51 {
55 };
56 static ChatCommandTable characterDeletedCommandTable =
57 {
62 };
63
64 static ChatCommandTable characterCommandTable =
65 {
70 { "deleted", characterDeletedCommandTable },
76 };
77
78 static ChatCommandTable commandTable =
79 {
80 { "character", characterCommandTable },
81 { "levelup", HandleLevelUpCommand, rbac::RBAC_PERM_COMMAND_LEVELUP, Console::No },
82 { "pdump", pdumpCommandTable },
83 };
84 return commandTable;
85 }
86
87 // Stores informations about a deleted character
89 {
91 std::string name;
93 std::string accountName;
94 time_t deleteDate;
95 };
96
97 typedef std::list<DeletedInfo> DeletedInfoList;
98
106 static bool GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string_view searchString)
107 {
108 PreparedQueryResult result;
110 if (!searchString.empty())
111 {
112 // search by GUID
113 if (Optional<uint64> guidValue = Trinity::StringTo<uint64>(searchString))
114 {
115 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID);
116 stmt->setUInt64(0, *guidValue);
117 result = CharacterDatabase.Query(stmt);
118 }
119 // search by name
120 else
121 {
122 std::string normalizedName(searchString);
123 if (!normalizePlayerName(normalizedName))
124 return false;
125
126 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME);
127 stmt->setString(0, normalizedName);
128 result = CharacterDatabase.Query(stmt);
129 }
130 }
131 else
132 {
133 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO);
134 result = CharacterDatabase.Query(stmt);
135 }
136
137 if (result)
138 {
139 do
140 {
141 Field* fields = result->Fetch();
142
143 DeletedInfo info;
144
145 info.guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
146 info.name = fields[1].GetString();
147 info.accountId = fields[2].GetUInt32();
148
149 // account name will be empty for nonexisting account
151 info.deleteDate = fields[3].GetInt64();
152 foundList.push_back(info);
153 }
154 while (result->NextRow());
155 }
156
157 return true;
158 }
159
170 static void HandleCharacterDeletedListHelper(DeletedInfoList const& foundList, ChatHandler* handler)
171 {
172 if (!handler->GetSession())
173 {
177 }
178
179 for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
180 {
181 std::string dateStr = TimeToTimestampStr(itr->deleteDate);
182
183 if (!handler->GetSession())
185 Trinity::ToString(itr->guid.GetCounter()), itr->name.c_str(), itr->accountName.empty() ? "<Not existing>" : itr->accountName.c_str(),
186 itr->accountId, dateStr.c_str());
187 else
189 Trinity::ToString(itr->guid.GetCounter()), itr->name.c_str(), itr->accountName.empty() ? "<Not existing>" : itr->accountName.c_str(),
190 itr->accountId, dateStr.c_str());
191 }
192
193 if (!handler->GetSession())
195 }
196
207 static void HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo, ChatHandler* handler)
208 {
209 if (delInfo.accountName.empty()) // account does not exist
210 {
212 return;
213 }
214
215 // check character count
217 if (charcount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
218 {
220 return;
221 }
222
223 if (!sCharacterCache->GetCharacterGuidByName(delInfo.name).IsEmpty())
224 {
226 return;
227 }
228
230 stmt->setString(0, delInfo.name);
231 stmt->setUInt32(1, delInfo.accountId);
232 stmt->setUInt64(2, delInfo.guid.GetCounter());
233 CharacterDatabase.Execute(stmt);
234
235 sCharacterCache->UpdateCharacterInfoDeleted(delInfo.guid, false, delInfo.name);
236 }
237
239 {
240 if (!player)
241 player = PlayerIdentifier::FromTargetOrSelf(handler);
242 if (!player || !player->IsConnected())
243 {
245 handler->SetSentErrorMessage(true);
246 return false;
247 }
248
249 Player const* target = player->GetConnectedPlayer();
250
251 LocaleConstant loc = handler->GetSessionDbcLocale();
252 char const* knownStr = handler->GetTrinityString(LANG_KNOWN);
253
254 // Search in CharTitles.dbc
255 for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
256 {
257 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
258
259 if (titleInfo && target->HasTitle(titleInfo))
260 {
261 char const* name = target->GetNativeGender() == GENDER_MALE ? titleInfo->Name[loc] : titleInfo->Name1[loc];
262 if (!*name)
263 name = (target->GetNativeGender() == GENDER_MALE ? titleInfo->Name[sWorld->GetDefaultDbcLocale()] : titleInfo->Name1[sWorld->GetDefaultDbcLocale()]);
264 if (!*name)
265 continue;
266
267 char const* activeStr = "";
268 if (*target->m_playerData->PlayerTitle == titleInfo->MaskID)
269 activeStr = handler->GetTrinityString(LANG_ACTIVE);
270
271 std::string titleName = ChatHandler::PGetParseString(name, player->GetName());
272
273 // send title in "id (idx:idx) - [namedlink locale]" format
274 if (handler->GetSession())
275 handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, id, titleInfo->MaskID, id, titleName.c_str(), localeNames[loc], knownStr, activeStr);
276 else
277 handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, id, titleInfo->MaskID, name, localeNames[loc], knownStr, activeStr);
278 }
279 }
280
281 return true;
282 }
283
284 //rename characters
286 {
287 if (!player && newNameV)
288 return false;
289
290 if (!player)
291 player = PlayerIdentifier::FromTarget(handler);
292 if (!player)
293 return false;
294
295 if (handler->HasLowerSecurity(nullptr, player->GetGUID()))
296 return false;
297
298 if (newNameV)
299 {
300 std::string newName{ *newNameV };
301 if (!normalizePlayerName(newName))
302 {
304 handler->SetSentErrorMessage(true);
305 return false;
306 }
307
308 if (ObjectMgr::CheckPlayerName(newName, player->IsConnected() ? player->GetConnectedPlayer()->GetSession()->GetSessionDbcLocale() : sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS)
309 {
311 handler->SetSentErrorMessage(true);
312 return false;
313 }
314
315 if (WorldSession* session = handler->GetSession())
316 {
317 if (!session->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName))
318 {
320 handler->SetSentErrorMessage(true);
321 return false;
322 }
323 }
324
326 stmt->setString(0, newName);
327 PreparedQueryResult result = CharacterDatabase.Query(stmt);
328 if (result)
329 {
330 handler->PSendSysMessage(LANG_RENAME_PLAYER_ALREADY_EXISTS, newName.c_str());
331 handler->SetSentErrorMessage(true);
332 return false;
333 }
334
335 // Remove declined name from db
336 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
337 stmt->setUInt64(0, player->GetGUID().GetCounter());
338 CharacterDatabase.Execute(stmt);
339
340 if (Player* target = player->GetConnectedPlayer())
341 {
342 target->SetName(newName);
343
344 if (WorldSession* session = target->GetSession())
345 session->KickPlayer("HandleCharacterRenameCommand GM Command renaming character");
346 }
347 else
348 {
349 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME_BY_GUID);
350 stmt->setString(0, newName);
351 stmt->setUInt64(1, player->GetGUID().GetCounter());
352 CharacterDatabase.Execute(stmt);
353 }
354
355 sCharacterCache->UpdateCharacterData(*player, newName);
356
357 handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, player->GetName().c_str(), newName.c_str());
358
359 if (WorldSession* session = handler->GetSession())
360 {
361 if (Player* player = session->GetPlayer())
362 sLog->OutCommand(session->GetAccountId(), "GM {} (Account: {}) forced rename {} to player {} (Account: {})", player->GetName(), session->GetAccountId(), newName, player->GetName(), sCharacterCache->GetCharacterAccountIdByGuid(player->GetGUID()));
363 }
364 else
365 sLog->OutCommand(0, "CONSOLE forced rename '{}' to '{}' ({})", player->GetName(), newName, player->GetGUID().ToString());
366 }
367 else
368 {
369 if (Player* target = player->GetConnectedPlayer())
370 {
371 handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str());
372 target->SetAtLoginFlag(AT_LOGIN_RENAME);
373 }
374 else
375 {
376 // check offline security
377 if (handler->HasLowerSecurity(nullptr, player->GetGUID()))
378 return false;
379
380 handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
381
384 stmt->setUInt64(1, player->GetGUID().GetCounter());
385 CharacterDatabase.Execute(stmt);
386 }
387 }
388
389 return true;
390 }
391
392 // customize characters
394 {
395 if (!player)
396 player = PlayerIdentifier::FromTarget(handler);
397 if (!player)
398 return false;
399
400 if (Player* target = player->GetConnectedPlayer())
401 {
402 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
403 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
404 }
405 else
406 {
407 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
409 stmt->setUInt16(0, static_cast<uint16>(AT_LOGIN_CUSTOMIZE));
410 stmt->setUInt64(1, player->GetGUID().GetCounter());
411 CharacterDatabase.Execute(stmt);
412 }
413
414 return true;
415 }
416
418 {
419 if (!player)
420 player = PlayerIdentifier::FromTarget(handler);
421 if (!player)
422 return false;
423
424 if (Player* target = player->GetConnectedPlayer())
425 {
426 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
427 target->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION);
428 }
429 else
430 {
431 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
434 stmt->setUInt64(1, player->GetGUID().GetCounter());
435 CharacterDatabase.Execute(stmt);
436 }
437
438 return true;
439 }
440
442 {
443 if (!player)
444 player = PlayerIdentifier::FromTarget(handler);
445 if (!player)
446 return false;
447
448 if (Player* target = player->GetConnectedPlayer())
449 {
450 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
451 target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE);
452 }
453 else
454 {
455 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
458 stmt->setUInt64(1, player->GetGUID().GetCounter());
459 CharacterDatabase.Execute(stmt);
460 }
461
462 return true;
463 }
464
466 {
467 if (!player)
468 player = PlayerIdentifier::FromTarget(handler);
469 if (!player)
470 return false;
471
472 CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(player->GetGUID());
473 if (!characterInfo)
474 {
476 handler->SetSentErrorMessage(true);
477 return false;
478 }
479
480 uint32 oldAccountId = characterInfo->AccountId;
481 // nothing to do :)
482 if (newAccount.GetID() == oldAccountId)
483 return true;
484
485 if (uint32 charCount = AccountMgr::GetCharactersCount(newAccount.GetID()))
486 {
487 if (charCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
488 {
489 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, newAccount.GetName().c_str(), newAccount.GetID());
490 handler->SetSentErrorMessage(true);
491 return false;
492 }
493 }
494
495 if (Player* onlinePlayer = player->GetConnectedPlayer())
496 onlinePlayer->GetSession()->KickPlayer("HandleCharacterChangeAccountCommand GM Command transferring character to another account");
497
499 charStmt->setUInt32(0, newAccount.GetID());
500 charStmt->setUInt64(1, player->GetGUID().GetCounter());
501 CharacterDatabase.DirectExecute(charStmt);
502
503 sWorld->UpdateRealmCharCount(oldAccountId);
504 sWorld->UpdateRealmCharCount(newAccount.GetID());
505
506 sCharacterCache->UpdateCharacterAccountId(*player, newAccount.GetID());
507
508 handler->PSendSysMessage(LANG_CHANGEACCOUNT_SUCCESS, player->GetName().c_str(), newAccount.GetName().c_str());
509
510 std::string logString = Trinity::StringFormat("changed ownership of player {} ({}) from account {} to account {}", player->GetName(), player->GetGUID().ToString(), oldAccountId, newAccount.GetID());
511 if (WorldSession* session = handler->GetSession())
512 {
513 if (Player* player = session->GetPlayer())
514 sLog->OutCommand(session->GetAccountId(), "GM {} (Account: {}) {}", player->GetName(), session->GetAccountId(), logString);
515 }
516 else
517 sLog->OutCommand(0, "{} {}", handler->GetTrinityString(LANG_CONSOLE), logString);
518 return true;
519 }
520
522 {
523 if (!player)
524 player = PlayerIdentifier::FromTargetOrSelf(handler);
525 if (!player || !player->IsConnected())
526 {
528 handler->SetSentErrorMessage(true);
529 return false;
530 }
531
532 Player const* target = player->GetConnectedPlayer();
533 LocaleConstant loc = handler->GetSessionDbcLocale();
534
535 FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList();
536 for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr)
537 {
538 FactionState const& faction = itr->second;
539 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction.ID);
540 char const* factionName = factionEntry ? factionEntry->Name[loc] : "#Not found#";
541 std::string rankName = target->GetReputationMgr().GetReputationRankName(factionEntry);
542 std::ostringstream ss;
543 if (handler->GetSession())
544 ss << faction.ID << " - |cffffffff|Hfaction:" << faction.ID << "|h[" << factionName << ' ' << localeNames[loc] << "]|h|r";
545 else
546 ss << faction.ID << " - " << factionName << ' ' << localeNames[loc];
547
548 ss << ' ' << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ')';
549
553 ss << handler->GetTrinityString(LANG_FACTION_ATWAR);
562
563 handler->SendSysMessage(ss.view());
564 }
565
566 return true;
567 }
568
580 {
581 DeletedInfoList foundList;
582 if (!GetDeletedCharacterInfoList(foundList, needle.value_or(""sv)))
583 return false;
584
585 // if no characters have been found, output a warning
586 if (foundList.empty())
587 {
589 handler->SetSentErrorMessage(true);
590 return false;
591 }
592
593 HandleCharacterDeletedListHelper(foundList, handler);
594
595 return true;
596 }
597
611 static bool HandleCharacterDeletedRestoreCommand(ChatHandler* handler, std::string_view needle, Optional<std::string_view> const& newCharName, Optional<AccountIdentifier> const& newAccount)
612 {
613 DeletedInfoList foundList;
614 if (!GetDeletedCharacterInfoList(foundList, needle))
615 return false;
616
617 if (foundList.empty())
618 {
620 handler->SetSentErrorMessage(true);
621 return false;
622 }
623
625 HandleCharacterDeletedListHelper(foundList, handler);
626
627 if (!newCharName)
628 {
629 // Drop nonexisting account cases
630 for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
632 return true;
633 }
634
635 if (foundList.size() == 1)
636 {
637 std::string newName{ *newCharName };
638 DeletedInfo delInfo = foundList.front();
639
640 // update name
641 delInfo.name = newName;
642
643 // if new account provided update deleted info
644 if (newAccount)
645 {
646 delInfo.accountId = newAccount->GetID();
647 delInfo.accountName = newAccount->GetName();
648 }
649
650 HandleCharacterDeletedRestoreHelper(delInfo, handler);
651 return true;
652 }
653
655 handler->SetSentErrorMessage(true);
656 return false;
657 }
658
669 static bool HandleCharacterDeletedDeleteCommand(ChatHandler* handler, std::string_view needle)
670 {
671 DeletedInfoList foundList;
672 if (!GetDeletedCharacterInfoList(foundList, needle))
673 return false;
674
675 if (foundList.empty())
676 {
678 handler->SetSentErrorMessage(true);
679 return false;
680 }
681
683 HandleCharacterDeletedListHelper(foundList, handler);
684
685 // Call the appropriate function to delete them (current account for deleted characters is 0)
686 for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
687 Player::DeleteFromDB(itr->guid, 0, false, true);
688
689 return true;
690 }
691
704 {
705 int32 keepDays = static_cast<int32>(sWorld->getIntConfig(CONFIG_CHARDELETE_KEEP_DAYS));
706
707 if (days)
708 keepDays = static_cast<int32>(*days);
709 else if (keepDays <= 0) // config option value 0 -> disabled and can't be used
710 return false;
711
712 Player::DeleteOldCharacters(static_cast<uint32>(keepDays));
713
714 return true;
715 }
716
718 {
719 uint32 accountId;
720 if (Player* target = player.GetConnectedPlayer())
721 {
722 accountId = target->GetSession()->GetAccountId();
723 target->GetSession()->KickPlayer("HandleCharacterEraseCommand GM Command deleting character");
724 }
725 else
726 accountId = sCharacterCache->GetCharacterAccountIdByGuid(player);
727
728 std::string accountName;
729 AccountMgr::GetName(accountId, accountName);
730
731 Player::DeleteFromDB(player, accountId, true, true);
732 handler->PSendSysMessage(LANG_CHARACTER_DELETED, player.GetName().c_str(), player.GetGUID().ToString().c_str(), accountName.c_str(), accountId);
733
734 return true;
735 }
736
738 {
739 if (!player)
740 player = PlayerIdentifier::FromTargetOrSelf(handler);
741 if (!player)
742 return false;
743
744 uint8 oldlevel = static_cast<uint8>(player->IsConnected() ? player->GetConnectedPlayer()->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(*player));
745
746 if (newlevel < 1)
747 newlevel = 1;
748
749 if (newlevel > static_cast<int16>(STRONG_MAX_LEVEL))
750 newlevel = static_cast<int16>(STRONG_MAX_LEVEL);
751
752 if (Player* target = player->GetConnectedPlayer())
753 {
754 target->GiveLevel(static_cast<uint8>(newlevel));
755 target->InitTalentForLevel();
756 target->SetXP(0);
757
758 if (handler->needReportToTarget(target))
759 {
760 if (oldlevel == newlevel)
761 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET, handler->GetNameLink().c_str());
762 else if (oldlevel < static_cast<uint8>(newlevel))
763 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_UP, handler->GetNameLink().c_str(), newlevel);
764 else // if (oldlevel > newlevel)
765 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_DOWN, handler->GetNameLink().c_str(), newlevel);
766 }
767 }
768 else
769 {
770 // Update level and reset XP, everything else will be updated at login
772 stmt->setUInt8(0, static_cast<uint8>(newlevel));
773 stmt->setUInt64(1, player->GetGUID().GetCounter());
774 CharacterDatabase.Execute(stmt);
775 }
776
777 if (!handler->GetSession() || (handler->GetSession()->GetPlayer() != player->GetConnectedPlayer())) // including chr == NULL
778 handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, handler->playerLink(*player).c_str(), newlevel);
779
780 return true;
781 }
782
784 {
785 if (!player)
786 player = PlayerIdentifier::FromTargetOrSelf(handler);
787 if (!player)
788 return false;
789
790 uint8 oldlevel = static_cast<uint8>(player->IsConnected() ? player->GetConnectedPlayer()->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(*player));
791 int16 newlevel = static_cast<int16>(oldlevel) + level;
792
793 if (newlevel < 1)
794 newlevel = 1;
795
796 if (newlevel > static_cast<int16>(STRONG_MAX_LEVEL))
797 newlevel = static_cast<int16>(STRONG_MAX_LEVEL);
798
799 if (Player* target = player->GetConnectedPlayer())
800 {
801 target->GiveLevel(static_cast<uint8>(newlevel));
802 target->InitTalentForLevel();
803 target->SetXP(0);
804
805 if (handler->needReportToTarget(target))
806 {
807 if (oldlevel == newlevel)
808 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET, handler->GetNameLink().c_str());
809 else if (oldlevel < static_cast<uint8>(newlevel))
810 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_UP, handler->GetNameLink().c_str(), newlevel);
811 else // if (oldlevel > newlevel)
812 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_DOWN, handler->GetNameLink().c_str(), newlevel);
813 }
814 }
815 else
816 {
817 // Update level and reset XP, everything else will be updated at login
819 stmt->setUInt8(0, static_cast<uint8>(newlevel));
820 stmt->setUInt64(1, player->GetGUID().GetCounter());
821 CharacterDatabase.Execute(stmt);
822 }
823
824 if (!handler->GetSession() || (handler->GetSession()->GetPlayer() != player->GetConnectedPlayer())) // including chr == NULL
825 handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, handler->playerLink(*player).c_str(), newlevel);
826
827 return true;
828 }
829
831 {
832 std::string name;
833 if (!ValidatePDumpTarget(handler, name, characterName, characterGUID))
834 return false;
835
836 std::string dump;
837 switch (PlayerDumpWriter().WriteDumpToString(dump, player.GetGUID().GetCounter()))
838 {
839 case DUMP_SUCCESS:
840 break;
843 handler->SetSentErrorMessage(true);
844 return false;
845 case DUMP_FILE_OPEN_ERROR: // this error code should not happen
846 default:
848 handler->SetSentErrorMessage(true);
849 return false;
850 }
851
852 switch (PlayerDumpReader().LoadDumpFromString(dump, account, name, characterGUID.value_or(0)))
853 {
854 case DUMP_SUCCESS:
855 break;
857 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
858 handler->SetSentErrorMessage(true);
859 return false;
860 case DUMP_FILE_OPEN_ERROR: // this error code should not happen
861 case DUMP_FILE_BROKEN: // this error code should not happen
862 default:
864 handler->SetSentErrorMessage(true);
865 return false;
866 }
867
868 // ToDo: use a new trinity_string for this commands
870
871 return true;
872 }
873
874 static bool HandlePDumpLoadCommand(ChatHandler* handler, std::string fileName, AccountIdentifier account, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
875 {
876 std::string name;
877 if (!ValidatePDumpTarget(handler, name, characterName, characterGUID))
878 return false;
879
880 switch (PlayerDumpReader().LoadDumpFromFile(fileName, account, name, characterGUID.value_or(0)))
881 {
882 case DUMP_SUCCESS:
884 break;
886 handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileName.c_str());
887 handler->SetSentErrorMessage(true);
888 return false;
889 case DUMP_FILE_BROKEN:
890 handler->PSendSysMessage(LANG_DUMP_BROKEN, fileName.c_str());
891 handler->SetSentErrorMessage(true);
892 return false;
894 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
895 handler->SetSentErrorMessage(true);
896 return false;
897 default:
899 handler->SetSentErrorMessage(true);
900 return false;
901 }
902
903 return true;
904 }
905
906 static bool ValidatePDumpTarget(ChatHandler* handler, std::string& name, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
907 {
908 if (characterName)
909 {
910 name.assign(*characterName);
911 // normalize the name if specified and check if it exists
912 if (!normalizePlayerName(name))
913 {
915 handler->SetSentErrorMessage(true);
916 return false;
917 }
918
919 if (ObjectMgr::CheckPlayerName(name, sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS)
920 {
922 handler->SetSentErrorMessage(true);
923 return false;
924 }
925 }
926
927 if (characterGUID)
928 {
929 if (sCharacterCache->GetCharacterCacheByGuid(ObjectGuid::Create<HighGuid::Player>(*characterGUID)))
930 {
931 handler->PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, *characterGUID);
932 handler->SetSentErrorMessage(true);
933 return false;
934 }
935 }
936
937 return true;
938 }
939
940 static bool HandlePDumpWriteCommand(ChatHandler* handler, std::string fileName, PlayerIdentifier player)
941 {
942 switch (PlayerDumpWriter().WriteDumpToFile(fileName, player.GetGUID().GetCounter()))
943 {
944 case DUMP_SUCCESS:
946 break;
948 handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileName.c_str());
949 handler->SetSentErrorMessage(true);
950 return false;
953 handler->SetSentErrorMessage(true);
954 return false;
955 default:
957 handler->SetSentErrorMessage(true);
958 return false;
959 }
960
961 return true;
962 }
963};
964
#define sCharacterCache
@ CHAR_SEL_CHECK_NAME
@ CHAR_UPD_LEVEL
@ CHAR_SEL_CHAR_DEL_INFO_BY_NAME
@ CHAR_SEL_CHAR_DEL_INFO
@ CHAR_DEL_CHAR_DECLINED_NAME
@ CHAR_UPD_NAME_BY_GUID
@ CHAR_SEL_CHAR_DEL_INFO_BY_GUID
@ CHAR_UPD_ACCOUNT_BY_GUID
@ CHAR_UPD_ADD_AT_LOGIN_FLAG
@ CHAR_UPD_RESTORE_DELETE_INFO
char const * localeNames[TOTAL_LOCALES]
Definition Common.cpp:20
LocaleConstant
Definition Common.h:51
DB2Storage< CharTitlesEntry > sCharTitlesStore("CharTitles.db2", &CharTitlesLoadInfo::Instance)
DB2Storage< FactionEntry > sFactionStore("Faction.db2", &FactionLoadInfo::Instance)
@ STRONG_MAX_LEVEL
Definition DBCEnums.h:49
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:156
int16_t int16
Definition Define.h:151
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
@ LANG_FACTION_PEACE_FORCED
Definition Language.h:369
@ LANG_CHARACTER_DELETED_SKIP_NAME
Definition Language.h:862
@ LANG_CHARACTER_DELETED_LIST_LINE_CHAT
Definition Language.h:863
@ LANG_RENAME_PLAYER
Definition Language.h:301
@ LANG_FACTION_ATWAR
Definition Language.h:368
@ LANG_CHARACTER_DELETED_ERR_RENAME
Definition Language.h:859
@ LANG_CHARACTER_DELETED_LIST_HEADER
Definition Language.h:853
@ LANG_KNOWN
Definition Language.h:63
@ LANG_DUMP_BROKEN
Definition Language.h:890
@ LANG_CHARACTER_DELETED_LIST_LINE_CONSOLE
Definition Language.h:854
@ LANG_FACTION_INVISIBLE_FORCED
Definition Language.h:371
@ LANG_COMMAND_EXPORT_DELETED_CHAR
Definition Language.h:906
@ LANG_FILE_OPEN_FAIL
Definition Language.h:888
@ LANG_CHARACTER_GUID_IN_USE
Definition Language.h:893
@ LANG_CUSTOMIZE_PLAYER_GUID
Definition Language.h:401
@ LANG_ACCOUNT_CHARACTER_LIST_FULL
Definition Language.h:889
@ LANG_RENAME_PLAYER_WITH_NEW_NAME
Definition Language.h:131
@ LANG_YOU_CHANGE_LVL
Definition Language.h:163
@ LANG_TITLE_LIST_CHAT
Definition Language.h:404
@ LANG_CHARACTER_DELETED_RESTORE
Definition Language.h:857
@ LANG_CHARACTER_DELETED
Definition Language.h:846
@ LANG_COMMAND_EXPORT_SUCCESS
Definition Language.h:548
@ LANG_FACTION_HIDDEN
Definition Language.h:370
@ LANG_CONSOLE
Definition Language.h:1104
@ LANG_CUSTOMIZE_PLAYER
Definition Language.h:400
@ LANG_ACTIVE
Definition Language.h:67
@ LANG_PLAYER_NOT_FOUND
Definition Language.h:570
@ LANG_CHARACTER_DELETED_SKIP_FULL
Definition Language.h:861
@ LANG_CHARACTER_DELETED_LIST_EMPTY
Definition Language.h:856
@ LANG_CHARACTER_DELETED_LIST_BAR
Definition Language.h:855
@ LANG_BAD_VALUE
Definition Language.h:149
@ LANG_TITLE_LIST_CONSOLE
Definition Language.h:405
@ LANG_COMMAND_IMPORT_FAILED
Definition Language.h:547
@ LANG_YOURS_LEVEL_UP
Definition Language.h:641
@ LANG_YOURS_LEVEL_PROGRESS_RESET
Definition Language.h:643
@ LANG_RESERVED_NAME
Definition Language.h:208
@ LANG_COMMAND_EXPORT_FAILED
Definition Language.h:549
@ LANG_FACTION_INACTIVE
Definition Language.h:372
@ LANG_RENAME_PLAYER_ALREADY_EXISTS
Definition Language.h:130
@ LANG_CHARACTER_DELETED_SKIP_ACCOUNT
Definition Language.h:860
@ LANG_RENAME_PLAYER_GUID
Definition Language.h:302
@ LANG_CHANGEACCOUNT_SUCCESS
Definition Language.h:960
@ LANG_FACTION_VISIBLE
Definition Language.h:367
@ LANG_YOURS_LEVEL_DOWN
Definition Language.h:642
@ LANG_INVALID_CHARACTER_NAME
Definition Language.h:891
@ LANG_COMMAND_IMPORT_SUCCESS
Definition Language.h:546
@ LANG_CHARACTER_DELETED_DELETE
Definition Language.h:858
#define sLog
Definition Log.h:156
bool normalizePlayerName(std::string &name)
#define sObjectMgr
Definition ObjectMgr.h:1885
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ DUMP_FILE_OPEN_ERROR
Definition PlayerDump.h:67
@ DUMP_CHARACTER_DELETED
Definition PlayerDump.h:70
@ DUMP_SUCCESS
Definition PlayerDump.h:66
@ DUMP_TOO_MANY_CHARS
Definition PlayerDump.h:68
@ DUMP_FILE_BROKEN
Definition PlayerDump.h:69
@ AT_LOGIN_CUSTOMIZE
Definition Player.h:641
@ AT_LOGIN_RENAME
Definition Player.h:638
@ AT_LOGIN_CHANGE_RACE
Definition Player.h:645
@ AT_LOGIN_CHANGE_FACTION
Definition Player.h:644
std::map< RepListID, FactionState > FactionStateList
@ GENDER_MALE
@ CHAR_NAME_SUCCESS
std::string TimeToTimestampStr(time_t t)
Definition Util.cpp:254
static uint32 GetCharactersCount(uint32 accountId)
static bool GetName(uint32 accountId, std::string &name)
std::string playerLink(std::string const &name) const
Definition Chat.cpp:603
WorldSession * GetSession()
Definition Chat.h:42
virtual LocaleConstant GetSessionDbcLocale() const
Definition Chat.cpp:593
virtual std::string GetNameLink() const
Definition Chat.cpp:56
bool HasLowerSecurity(Player *target, ObjectGuid guid, bool strong=false)
Definition Chat.cpp:61
static std::string PGetParseString(std::string_view fmt, Args &&... args) noexcept
Definition Chat.h:74
void SetSentErrorMessage(bool val)
Definition Chat.h:127
void PSendSysMessage(char const *fmt, Args &&... args)
Definition Chat.h:62
virtual void SendSysMessage(std::string_view str, bool escapeCharacters=false)
Definition Chat.cpp:111
virtual bool needReportToTarget(Player *chr) const
Definition Chat.cpp:587
virtual char const * GetTrinityString(uint32 entry) const
Definition Chat.cpp:46
constexpr bool HasFlag(T flag) const
Definition EnumFlag.h:106
Class used to access individual fields of database query result.
Definition Field.h:94
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
std::string GetString() const noexcept
Definition Field.cpp:113
int64 GetInt64() const noexcept
Definition Field.cpp:78
LowType GetCounter() const
Definition ObjectGuid.h:336
std::string ToString() const
static ResponseCodes CheckPlayerName(std::string_view name, LocaleConstant locale, bool create=false)
UF::UpdateField< UF::PlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_PLAYER > m_playerData
Definition Player.h:3061
static void DeleteOldCharacters()
Definition Player.cpp:4281
Gender GetNativeGender() const override
Definition Player.h:1350
bool HasTitle(uint32 bitIndex) const
Definition Player.cpp:27052
static void DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRealmChars=true, bool deleteFinally=false)
Definition Player.cpp:3767
ReputationMgr & GetReputationMgr()
Definition Player.h:2439
void setUInt16(uint8 index, uint16 value)
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void setUInt64(uint8 index, uint64 value)
void setUInt8(uint8 index, uint8 value)
std::string GetReputationRankName(FactionEntry const *factionEntry) const
FactionStateList const & GetStateList() const
int32 GetReputation(uint32 faction_id) const
Player session in the World.
Player * GetPlayer() const
static bool GetDeletedCharacterInfoList(DeletedInfoList &foundList, std::string_view searchString)
static bool HandlePDumpLoadCommand(ChatHandler *handler, std::string fileName, AccountIdentifier account, Optional< std::string_view > characterName, Optional< ObjectGuid::LowType > characterGUID)
static bool HandleCharacterDeletedDeleteCommand(ChatHandler *handler, std::string_view needle)
static bool HandleLevelUpCommand(ChatHandler *handler, Optional< PlayerIdentifier > player, int16 level)
static bool HandleCharacterDeletedRestoreCommand(ChatHandler *handler, std::string_view needle, Optional< std::string_view > const &newCharName, Optional< AccountIdentifier > const &newAccount)
static bool HandleCharacterLevelCommand(ChatHandler *handler, Optional< PlayerIdentifier > player, int16 newlevel)
static void HandleCharacterDeletedRestoreHelper(DeletedInfo const &delInfo, ChatHandler *handler)
static bool HandlePDumpCopyCommand(ChatHandler *handler, PlayerIdentifier player, AccountIdentifier account, Optional< std::string_view > characterName, Optional< ObjectGuid::LowType > characterGUID)
static bool HandleCharacterCustomizeCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static bool HandleCharacterRenameCommand(ChatHandler *handler, Optional< PlayerIdentifier > player, Optional< std::string_view > newNameV)
static bool HandleCharacterChangeRaceCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static bool HandleCharacterDeletedOldCommand(ChatHandler *, Optional< uint16 > days)
static bool HandleCharacterChangeAccountCommand(ChatHandler *handler, Optional< PlayerIdentifier > player, AccountIdentifier newAccount)
static bool ValidatePDumpTarget(ChatHandler *handler, std::string &name, Optional< std::string_view > characterName, Optional< ObjectGuid::LowType > characterGUID)
static bool HandleCharacterTitlesCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static void HandleCharacterDeletedListHelper(DeletedInfoList const &foundList, ChatHandler *handler)
static bool HandlePDumpWriteCommand(ChatHandler *handler, std::string fileName, PlayerIdentifier player)
std::span< ChatCommandBuilder const > GetCommands() const override
static bool HandleCharacterReputationCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static bool HandleCharacterEraseCommand(ChatHandler *handler, PlayerIdentifier player)
static bool HandleCharacterDeletedListCommand(ChatHandler *handler, Optional< std::string_view > const &needle)
static bool HandleCharacterChangeFactionCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
std::list< DeletedInfo > DeletedInfoList
void AddSC_character_commandscript()
#define sWorld
Definition World.h:916
@ CONFIG_CHARDELETE_KEEP_DAYS
Definition World.h:365
@ CONFIG_CHARACTERS_PER_REALM
Definition World.h:257
ChatCommandBuilder const [] ChatCommandTable
Definition ChatCommand.h:49
std::string ToString(Type &&val, Params &&... params)
std::string StringFormat(FormatString< Args... > fmt, Args &&... args) noexcept
Default TC string format function.
@ RBAC_PERM_COMMAND_CHARACTER_CHANGERACE
Definition RBAC.h:190
@ RBAC_PERM_COMMAND_PDUMP_COPY
Definition RBAC.h:748
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD
Definition RBAC.h:195
@ RBAC_PERM_COMMAND_LEVELUP
Definition RBAC.h:201
@ RBAC_PERM_COMMAND_CHARACTER_LEVEL
Definition RBAC.h:197
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE
Definition RBAC.h:192
@ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME
Definition RBAC.h:70
@ RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION
Definition RBAC.h:189
@ RBAC_PERM_COMMAND_CHARACTER_TITLES
Definition RBAC.h:200
@ RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE
Definition RBAC.h:188
@ RBAC_PERM_COMMAND_CHARACTER_CHANGEACCOUNT
Definition RBAC.h:570
@ RBAC_PERM_COMMAND_CHARACTER_RENAME
Definition RBAC.h:198
@ RBAC_PERM_COMMAND_CHARACTER_ERASE
Definition RBAC.h:196
@ RBAC_PERM_COMMAND_PDUMP_LOAD
Definition RBAC.h:203
@ RBAC_PERM_COMMAND_CHARACTER_REPUTATION
Definition RBAC.h:199
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST
Definition RBAC.h:193
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE
Definition RBAC.h:194
@ RBAC_PERM_COMMAND_PDUMP_WRITE
Definition RBAC.h:204
LocalizedString Name1
LocalizedString Name
LocalizedString Name
EnumFlag< ReputationFlags > Flags
static Optional< PlayerIdentifier > FromTarget(ChatHandler *handler)
std::string const & GetName() const
static Optional< PlayerIdentifier > FromTargetOrSelf(ChatHandler *handler)
std::string name
the character name
std::string accountName
the account name
time_t deleteDate
the date at which the character has been deleted
ObjectGuid guid
the GUID from the character