AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
PlayerDumpReader Class Reference

#include "PlayerDump.h"

Inheritance diagram for PlayerDumpReader:
PlayerDump

Public Member Functions

 PlayerDumpReader ()
 
DumpReturn LoadDumpFromFile (std::string const &file, uint32 account, std::string name, ObjectGuid::LowType guid)
 
DumpReturn LoadDumpFromString (std::string const &dump, uint32 account, std::string name, ObjectGuid::LowType guid)
 

Private Member Functions

DumpReturn LoadDump (std::istream &input, uint32 account, std::string name, ObjectGuid::LowType guid)
 

Additional Inherited Members

- Static Public Member Functions inherited from PlayerDump
static void InitializeTables ()
 
- Protected Member Functions inherited from PlayerDump
 PlayerDump ()
 

Detailed Description

Constructor & Destructor Documentation

◆ PlayerDumpReader()

PlayerDumpReader::PlayerDumpReader ( )
inline
100{ }

Member Function Documentation

◆ LoadDump()

DumpReturn PlayerDumpReader::LoadDump ( std::istream &  input,
uint32  account,
std::string  name,
ObjectGuid::LowType  guid 
)
private
765{
766 uint32 charcount = AccountMgr::GetCharactersCount(account);
767 if (charcount >= 10)
768 return DUMP_TOO_MANY_CHARS;
769
770 std::string newguid, chraccount;
771
772 // make sure the same guid doesn't already exist and is safe to use
773 bool incHighest = true;
774 if (guid && guid < sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed())
775 {
777 stmt->SetData(0, guid);
778
779 if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
780 guid = sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed(); // use first free if exists
781 else
782 incHighest = false;
783 }
784 else
785 guid = sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed();
786
787 // normalize the name if specified and check if it exists
788 if (!normalizePlayerName(name))
789 name.clear();
790
792 {
794 stmt->SetData(0, name);
795
796 if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
797 name.clear(); // use the one from the dump
798 }
799 else
800 name.clear();
801
802 // name encoded or empty
803 newguid = std::to_string(guid);
804 chraccount = std::to_string(account);
805
806 std::map<ObjectGuid::LowType, ObjectGuid::LowType> items;
807 ObjectGuid::LowType itemLowGuidOffset = sObjectMgr->GetGenerator<HighGuid::Item>().GetNextAfterMaxUsed();
808
809 std::map<ObjectGuid::LowType, ObjectGuid::LowType> mails;
810 ObjectGuid::LowType mailLowGuidOffset = sObjectMgr->_mailId;
811
812 std::map<ObjectGuid::LowType, ObjectGuid::LowType> petIds;
813 ObjectGuid::LowType petLowGuidOffset = sObjectMgr->_hiPetNumber;
814
815 std::map<uint64, uint64> equipmentSetIds;
816 uint64 equipmentSetGuidOffset = sObjectMgr->_equipmentSetGuid;
817
818 std::string line;
819
820 uint8 gender = GENDER_NONE;
821 uint8 race = RACE_NONE;
822 uint8 playerClass = CLASS_NONE;
823 uint8 level = 1;
824
825 // for logs
826 size_t lineNumber = 0;
827
828 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
829 while (std::getline(input, line))
830 {
831 ++lineNumber;
832
833 // skip empty strings
834 size_t nw_pos = line.find_first_not_of(" \t\n\r\7");
835 if (nw_pos == std::string::npos)
836 continue;
837
838 // skip the important notes
839 static std::string const SkippedLine = "IMPORTANT NOTE:";
840 if (line.substr(nw_pos, SkippedLine.size()) == SkippedLine)
841 continue;
842
843 // determine table name and load type
844 std::string tn = GetTableName(line);
845 if (tn.empty())
846 {
847 LOG_ERROR("misc", "LoadPlayerDump: (line {}) Can't extract table name!", lineNumber);
848 return DUMP_FILE_BROKEN;
849 }
850
852 uint32 i;
853 for (i = 0; i < DUMP_TABLE_COUNT; ++i)
854 {
855 if (tn == DumpTables[i].Name)
856 {
857 type = DumpTables[i].Type;
858 break;
859 }
860 }
861
862 if (i == DUMP_TABLE_COUNT)
863 {
864 LOG_ERROR("misc", "LoadPlayerDump: (line {}) Unknown table: `{}`!", lineNumber, tn);
865 return DUMP_FILE_BROKEN;
866 }
867
868 TableStruct const& ts = CharacterTables[i];
869 if (!ValidateFields(ts, line, lineNumber))
870 return DUMP_FILE_BROKEN;
871
872 // per field guid offsetting
873 for (TableField const& field : ts.TableFields)
874 {
875 if (!field.IsDependentField)
876 continue;
877
878 switch (field.FieldGuidType)
879 {
881 if (!ChangeColumn(ts, line, field.FieldName, chraccount))
882 return DUMP_FILE_BROKEN;
883 break;
884 case GUID_TYPE_CHAR:
885 if (!ChangeColumn(ts, line, field.FieldName, newguid))
886 return DUMP_FILE_BROKEN;
887 break;
888 case GUID_TYPE_PET:
889 if (!ChangeGuid(ts, line, field.FieldName, petIds, petLowGuidOffset))
890 return DUMP_FILE_BROKEN;
891 break;
892 case GUID_TYPE_MAIL:
893 if (!ChangeGuid(ts, line, field.FieldName, mails, mailLowGuidOffset))
894 return DUMP_FILE_BROKEN;
895 break;
896 case GUID_TYPE_ITEM:
897 if (!ChangeGuid(ts, line, field.FieldName, items, itemLowGuidOffset, true))
898 return DUMP_FILE_BROKEN;
899 break;
901 if (!ChangeGuid(ts, line, field.FieldName, equipmentSetIds, equipmentSetGuidOffset))
902 return DUMP_FILE_BROKEN;
903 break;
904 case GUID_TYPE_NULL:
905 {
906 static std::string const NullString("NULL");
907 if (!ChangeColumn(ts, line, field.FieldName, NullString))
908 return DUMP_FILE_BROKEN;
909 break;
910 }
911 }
912 }
913
914 // extra modifications for other tables
915 switch (type)
916 {
917 case DTT_CHARACTER:
918 {
919 race = *Acore::StringTo<uint32>(GetColumn(ts, line, "race"));
920 playerClass = *Acore::StringTo<uint32>(GetColumn(ts, line, "class"));
921 gender = *Acore::StringTo<uint32>(GetColumn(ts, line, "gender"));
922 level = *Acore::StringTo<uint32>(GetColumn(ts, line, "level"));
923 if (name.empty())
924 {
925 // generate a temporary name
926 std::string guidPart = Acore::StringFormat("%X", guid);
927 std::size_t maxCharsFromOriginalName = MAX_PLAYER_NAME - guidPart.length();
928
929 name = GetColumn(ts, line, "name").substr(0, maxCharsFromOriginalName) + guidPart;
930
931 // characters.at_login set to "rename on login"
932 if (!ChangeColumn(ts, line, "name", name))
933 return DUMP_FILE_BROKEN;
934 if (!ChangeColumn(ts, line, "at_login", "1"))
935 return DUMP_FILE_BROKEN;
936 }
937 else if (!ChangeColumn(ts, line, "name", name)) // characters.name
938 return DUMP_FILE_BROKEN;
939 break;
940 }
941 default:
942 break;
943 }
944
945 FixNULLfields(line);
946
947 trans->Append(line.c_str());
948 }
949
950 if (input.fail() && !input.eof())
951 return DUMP_FILE_BROKEN;
952
953 CharacterDatabase.CommitTransaction(trans);
954
955 // in case of name conflict player has to rename at login anyway
956 sCharacterCache->AddCharacterCacheEntry(ObjectGuid(HighGuid::Player, guid), account, name, gender, race, playerClass, level);
957
958 sObjectMgr->GetGenerator<HighGuid::Item>().Set(sObjectMgr->GetGenerator<HighGuid::Item>().GetNextAfterMaxUsed() + items.size());
959 sObjectMgr->_mailId += mails.size();
960 sObjectMgr->_hiPetNumber += petIds.size();
961 sObjectMgr->_equipmentSetGuid += equipmentSetIds.size();
962
963 if (incHighest)
964 sObjectMgr->GetGenerator<HighGuid::Player>().Generate();
965
966 sWorld->UpdateRealmCharCount(account);
967
968 return DUMP_SUCCESS;
969}
std::uint8_t uint8
Definition: Define.h:110
std::uint32_t uint32
Definition: Define.h:108
std::uint64_t uint64
Definition: Define.h:107
#define LOG_ERROR(filterType__,...)
Definition: Log.h:157
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
Definition: DatabaseEnvFwd.h:70
std::shared_ptr< PreparedResultSet > PreparedQueryResult
Definition: DatabaseEnvFwd.h:46
@ CHAR_SEL_CHECK_NAME
Definition: CharacterDatabase.h:37
@ CHAR_SEL_CHECK_GUID
Definition: CharacterDatabase.h:38
#define sCharacterCache
Definition: CharacterCache.h:83
bool normalizePlayerName(std::string &name)
Definition: ObjectMgr.cpp:262
#define MAX_PLAYER_NAME
Definition: ObjectMgr.h:688
#define sObjectMgr
Definition: ObjectMgr.h:1640
std::string GetColumn(TableStruct const &ts, std::string &str, std::string const &column)
Definition: PlayerDump.cpp:483
bool ChangeGuid(TableStruct const &ts, std::string &str, std::string const &column, MapType< T, T, Rest... > &guidMap, T guidOffset, bool allowZero=false)
Definition: PlayerDump.cpp:505
bool ChangeColumn(TableStruct const &ts, std::string &str, std::string const &column, std::string const &with, bool allowZero=false)
Definition: PlayerDump.cpp:470
uint32 const DUMP_TABLE_COUNT
Definition: PlayerDump.cpp:123
@ GUID_TYPE_NULL
Definition: PlayerDump.cpp:45
@ GUID_TYPE_MAIL
Definition: PlayerDump.cpp:38
@ GUID_TYPE_PET
Definition: PlayerDump.cpp:37
@ GUID_TYPE_EQUIPMENT_SET
Definition: PlayerDump.cpp:42
@ GUID_TYPE_CHAR
Definition: PlayerDump.cpp:36
@ GUID_TYPE_ITEM
Definition: PlayerDump.cpp:39
@ GUID_TYPE_ACCOUNT
Definition: PlayerDump.cpp:35
DumpTable const DumpTables[]
Definition: PlayerDump.cpp:88
void FixNULLfields(std::string &line)
Definition: PlayerDump.cpp:753
std::vector< TableStruct > CharacterTables
Definition: PlayerDump.cpp:166
std::string GetTableName(std::string const &str)
Definition: PlayerDump.cpp:418
bool ValidateFields(TableStruct const &ts, std::string const &str, size_t lineNumber)
Definition: PlayerDump.cpp:429
@ DUMP_SUCCESS
Definition: PlayerDump.h:57
@ DUMP_TOO_MANY_CHARS
Definition: PlayerDump.h:59
@ DUMP_FILE_BROKEN
Definition: PlayerDump.h:60
DumpTableType
Definition: PlayerDump.h:28
@ DTT_CHARACTER
Definition: PlayerDump.h:29
@ GENDER_NONE
Definition: SharedDefines.h:63
@ CHAR_NAME_SUCCESS
Definition: SharedDefines.h:3419
@ CLASS_NONE
Definition: SharedDefines.h:140
@ RACE_NONE
Definition: SharedDefines.h:70
#define sWorld
Definition: World.h:447
std::string StringFormat(Format &&fmt, Args &&... args)
Default AC string format function.
Definition: StringFormat.h:30
uint32 GetCharactersCount(uint32 accountId)
Definition: AccountMgr.cpp:266
Definition: PreparedStatement.h:158
Acore::Types::is_default< T > SetData(const uint8 index, T value)
Definition: PreparedStatement.h:78
Definition: ObjectGuid.h:120
uint32 LowType
Definition: ObjectGuid.h:124
static uint8 CheckPlayerName(std::string_view name, bool create=false)
Definition: ObjectMgr.cpp:8362
DumpTableType Type
Definition: PlayerDump.cpp:85
Definition: PlayerDump.cpp:149
bool IsDependentField
Definition: PlayerDump.cpp:153
std::string FieldName
Definition: PlayerDump.cpp:150
GuidType FieldGuidType
Definition: PlayerDump.cpp:152
Definition: PlayerDump.cpp:157
std::vector< TableField > TableFields
Definition: PlayerDump.cpp:160

References ChangeColumn(), ChangeGuid(), CHAR_NAME_SUCCESS, CHAR_SEL_CHECK_GUID, CHAR_SEL_CHECK_NAME, CharacterDatabase, CharacterTables, ObjectMgr::CheckPlayerName(), CLASS_NONE, DTT_CHARACTER, DUMP_FILE_BROKEN, DUMP_SUCCESS, DUMP_TABLE_COUNT, DUMP_TOO_MANY_CHARS, DumpTables, TableField::FieldGuidType, TableField::FieldName, FixNULLfields(), GENDER_NONE, AccountMgr::GetCharactersCount(), GetColumn(), GetTableName(), GUID_TYPE_ACCOUNT, GUID_TYPE_CHAR, GUID_TYPE_EQUIPMENT_SET, GUID_TYPE_ITEM, GUID_TYPE_MAIL, GUID_TYPE_NULL, GUID_TYPE_PET, TableField::IsDependentField, LOG_ERROR, MAX_PLAYER_NAME, normalizePlayerName(), RACE_NONE, sCharacterCache, PreparedStatementBase::SetData(), sObjectMgr, Acore::StringFormat(), sWorld, TableStruct::TableFields, DumpTable::Type, and ValidateFields().

Referenced by LoadDumpFromFile(), and LoadDumpFromString().

◆ LoadDumpFromFile()

DumpReturn PlayerDumpReader::LoadDumpFromFile ( std::string const &  file,
uint32  account,
std::string  name,
ObjectGuid::LowType  guid 
)
978{
979 std::ifstream input(file);
980 if (!input)
982 return LoadDump(input, account, name, guid);
983}
@ DUMP_FILE_OPEN_ERROR
Definition: PlayerDump.h:58
DumpReturn LoadDump(std::istream &input, uint32 account, std::string name, ObjectGuid::LowType guid)
Definition: PlayerDump.cpp:764

References DUMP_FILE_OPEN_ERROR, and LoadDump().

◆ LoadDumpFromString()

DumpReturn PlayerDumpReader::LoadDumpFromString ( std::string const &  dump,
uint32  account,
std::string  name,
ObjectGuid::LowType  guid 
)
972{
973 std::istringstream input(dump);
974 return LoadDump(input, account, name, guid);
975}

References LoadDump().