DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { uint32 charcount = accmgr.GetCharactersCount(account); if (charcount >= 10) return DUMP_TOO_MANY_CHARS; FILE *fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid != 0 && guid < objmgr.m_hiCharGuid) { result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE guid = '%d'", guid); if (result) guid = objmgr.m_hiCharGuid; // use first free if exists else incHighest = false; } else guid = objmgr.m_hiCharGuid; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name = ""; if (ObjectMgr::CheckPlayerName(name,true) == CHAR_NAME_SUCCESS) { CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE name = '%s'", name.c_str()); if (result) name = ""; // use the one from the dump } else name = ""; // name encoded or empty snprintf(newguid, 20, "%d", guid); snprintf(chraccount, 20, "%d", account); snprintf(newpetid, 20, "%d", objmgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32,uint32> items; std::map<uint32,uint32> mails; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; CharacterDatabase.BeginTransaction(); while (!feof(fin)) { if (!fgets(buf, 32000, fin)) { if (feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if (nw_pos == std::string::npos) continue; // skip logfile-side dump start notice, the important notes and dump end notices if ((line.substr(nw_pos,16) == "== START DUMP ==") || (line.substr(nw_pos,15) == "IMPORTANT NOTE:") || (line.substr(nw_pos,14) == "== END DUMP ==")) continue; // add required_ check /* if (line.substr(nw_pos,41) == "UPDATE character_db_version SET required_") { if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } */ // determine table name and load type std::string tn = gettablename(line); if (tn.empty()) { sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type; uint8 i; for (i = 0; i < DUMP_TABLE_COUNT; ++i) { if (tn == dumpTables[i].name) { type = dumpTables[i].type; break; } } if (i == DUMP_TABLE_COUNT) { sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } // change the data to server values switch(type) { case DTT_CHAR_TABLE: if (!changenth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHARACTER: { if (!changenth(line, 1, newguid)) // characters.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); if (name == "") { // check if the original name already exists name = getnth(line, 3); CharacterDatabase.escape_string(name); result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE name = '%s'", name.c_str()); if (result) { if (!changenth(line, 37, "1")) // characters.at_login set to "rename on login" ROLLBACK(DUMP_FILE_BROKEN); } } else if (!changenth(line, 3, name.c_str())) // characters.name ROLLBACK(DUMP_FILE_BROKEN); const char null[5] = "NULL"; if (!changenth(line, 68, null)) // characters.deleteInfos_Account ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 69, null)) // characters.deleteInfos_Name ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 70, null)) // characters.deleteDate ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_INVENTORY: { if (!changenth(line, 1, newguid)) // character_inventory.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, objmgr.m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update if (!changeGuid(line, 4, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update break; } case DTT_ITEM: { // item, owner, data field:item, owner guid if (!changeGuid(line, 1, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if (!changenth(line, 2, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: { if (!changenth(line, 1, newguid)) // character_gifts.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update break; } case DTT_PET: { //store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if (strlen(lastpetid) == 0) snprintf(lastpetid, 20, "%s", currpetid); if (strcmp(lastpetid,currpetid) != 0) { snprintf(newpetid, 20, "%d", objmgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } if (!changenth(line, 1, newpetid)) // character_pet.id update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, newguid)) // character_pet.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if (!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL: // mail { if (!changeGuid(line, 1, mails, objmgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); // mail.id update if (!changenth(line, 6, newguid)) // mail.receiver update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { if (!changeGuid(line, 1, mails, objmgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id if (!changeGuid(line, 2, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid if (!changenth(line, 4, newguid)) // mail_items.receiver ROLLBACK(DUMP_FILE_BROKEN); break; } default: sLog.outError("Unknown dump table type: %u",type); break; } fixNULLfields(line); if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); } CharacterDatabase.CommitTransaction(); objmgr.m_hiItemGuid += items.size(); objmgr.m_mailid += mails.size(); if (incHighest) ++objmgr.m_hiCharGuid; fclose(fin); return DUMP_SUCCESS; }
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { bool nameInvalidated = false; // set when name changed or will requested changed at next login // check character count uint32 charcount = sAccountMgr.GetCharactersCount(account); if (charcount >= 10) return DUMP_TOO_MANY_CHARS; FILE* fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; QueryResult* result = NULL; char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid != 0 && guid < sObjectMgr.m_CharGuids.GetNextAfterMaxUsed()) { result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%u'", guid); if (result) { guid = sObjectMgr.m_CharGuids.GetNextAfterMaxUsed(); delete result; } else incHighest = false; } else guid = sObjectMgr.m_CharGuids.GetNextAfterMaxUsed(); // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name = ""; if (ObjectMgr::CheckPlayerName(name, true) == CHAR_NAME_SUCCESS) { CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); if (result) { name = ""; // use the one from the dump delete result; } } else name = ""; // name encoded or empty snprintf(newguid, 20, "%u", guid); snprintf(chraccount, 20, "%u", account); snprintf(newpetid, 20, "%u", sObjectMgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32, uint32> items; std::map<uint32, uint32> mails; std::map<uint32, uint32> itemTexts; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; CharacterDatabase.BeginTransaction(); while (!feof(fin)) { if (!fgets(buf, 32000, fin)) { if (feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if (nw_pos == std::string::npos) continue; // skip NOTE if (line.substr(nw_pos, 15) == "IMPORTANT NOTE:") continue; // add required_ check if (line.substr(nw_pos, 41) == "UPDATE character_db_version SET required_") { if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } // determine table name and load type std::string tn = gettablename(line); if (tn.empty()) { sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type = DTT_CHARACTER; // Fixed: Using uninitialized memory 'type' DumpTable* dTable = &dumpTables[0]; for (; dTable->isValid(); ++dTable) { if (tn == dTable->name) { type = dTable->type; break; } } if (!dTable->isValid()) { sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } bool execute_ok = true; // false, if need skip soem query // change the data to server values switch (type) { case DTT_CHAR_TABLE: if (!changenth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHAR_NAME_TABLE: if (nameInvalidated) // ignore declined names if name will changed in some way { execute_ok = false; break; } if (!changenth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHARACTER: { if (!changenth(line, 1, newguid)) // characters.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); if (name == "") { // check if the original name already exists name = getnth(line, 3); // characters.name CharacterDatabase.escape_string(name); result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); if (result) { delete result; if (!changenth(line, 36, "1")) // characters.at_login set to "rename on login" ROLLBACK(DUMP_FILE_BROKEN); nameInvalidated = true; } } else { if (!changenth(line, 3, name.c_str())) // characters.name update ROLLBACK(DUMP_FILE_BROKEN); nameInvalidated = true; } break; } case DTT_INVENTORY: { if (!changenth(line, 1, newguid)) // character_inventory.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed(), true)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update if (!changeGuid(line, 4, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update break; } case DTT_ITEM: { // item, owner, data field:item, owner guid if (!changeGuid(line, 1, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if (!changenth(line, 2, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); std::string vals = getnth(line, 3); // item_instance.data get if (!changetokGuid(vals, OBJECT_FIELD_GUID + 1, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.data.OBJECT_FIELD_GUID update if (!changetoknth(vals, ITEM_FIELD_OWNER + 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.data.ITEM_FIELD_OWNER update if (!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID + 1, itemTexts, sObjectMgr.m_ItemTextIds.GetNextAfterMaxUsed(), true)) ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, vals.c_str())) // item_instance.data update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: { if (!changenth(line, 1, newguid)) // character_gifts.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update break; } case DTT_ITEM_LOOT: { // item, owner if (!changeGuid(line, 1, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // item_loot.guid update if (!changenth(line, 2, newguid)) // item_Loot.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET: { // store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if (strlen(lastpetid) == 0) snprintf(lastpetid, 20, "%s", currpetid); if (strcmp(lastpetid, currpetid) != 0) { snprintf(newpetid, 20, "%d", sObjectMgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } if (!changenth(line, 1, newpetid)) // character_pet.id update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, newguid)) // character_pet.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if (!changenth(line, 1, newpetid)) // pet_*.guid -> petid in fact ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_DECL: // character_pet_declinedname { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if (!changenth(line, 1, newpetid)) // character_pet_declinedname.id ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 2, newguid)) // character_pet_declinedname.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL: // mail { if (!changeGuid(line, 1, mails, sObjectMgr.m_MailIds.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // mail.id update if (!changenth(line, 6, newguid)) // mail.receiver update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 8, itemTexts, sObjectMgr.m_ItemTextIds.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { if (!changeGuid(line, 1, mails, sObjectMgr.m_MailIds.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid if (!changenth(line, 4, newguid)) // mail_items.receiver ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_TEXT: // item_text { // id if (!changeGuid(line, 1, itemTexts, sObjectMgr.m_ItemTextIds.GetNextAfterMaxUsed())) ROLLBACK(DUMP_FILE_BROKEN); // add it to cache uint32 id = atoi(getnth(line, 1).c_str()); std::string text = getnth(line, 2); sObjectMgr.AddItemText(id, text); break; } default: sLog.outError("Unknown dump table type: %u", type); break; } if (execute_ok && !CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); } CharacterDatabase.CommitTransaction(); // FIXME: current code with post-updating guids not safe for future per-map threads sObjectMgr.m_ItemGuids.Set(sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed() + items.size()); sObjectMgr.m_MailIds.Set(sObjectMgr.m_MailIds.GetNextAfterMaxUsed() + mails.size()); sObjectMgr.m_ItemTextIds.Set(sObjectMgr.m_ItemTextIds.GetNextAfterMaxUsed() + itemTexts.size()); if (incHighest) sObjectMgr.m_CharGuids.Set(sObjectMgr.m_CharGuids.GetNextAfterMaxUsed() + 1); fclose(fin); return DUMP_SUCCESS; }
DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, std::string name, uint32 guid) { uint32 charcount = AccountMgr::GetCharactersCount(account); if (charcount >= 10) return DUMP_TOO_MANY_CHARS; FILE* fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid != 0 && guid < sObjectMgr->_hiCharGuid) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_GUID); stmt->setUInt32(0, guid); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) guid = sObjectMgr->_hiCharGuid; // use first free if exists else incHighest = false; } else guid = sObjectMgr->_hiCharGuid; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name = ""; if (ObjectMgr::CheckPlayerName(name, true) == CHAR_NAME_SUCCESS) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, name); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) name = ""; // use the one from the dump } else name = ""; // name encoded or empty snprintf(newguid, 20, "%u", guid); snprintf(chraccount, 20, "%u", account); snprintf(newpetid, 20, "%u", sObjectMgr->GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32, uint32> items; std::map<uint32, uint32> mails; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; uint8 gender = GENDER_NONE; uint8 race = RACE_NONE; uint8 playerClass = 0; uint8 level = 1; SQLTransaction trans = CharacterDatabase.BeginTransaction(); while (!feof(fin)) { if (!fgets(buf, 32000, fin)) { if (feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if (nw_pos == std::string::npos) continue; // skip logfile-side dump start notice, the important notes and dump end notices if ((line.substr(nw_pos, 16) == "== START DUMP ==") || (line.substr(nw_pos, 15) == "IMPORTANT NOTE:") || (line.substr(nw_pos, 14) == "== END DUMP ==")) continue; // add required_ check /* if (line.substr(nw_pos, 41) == "UPDATE character_db_version SET required_") { if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } */ // determine table name and load type std::string tn = gettablename(line); if (tn.empty()) { TC_LOG_ERROR("misc", "LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type = DumpTableType(0); uint8 i; for (i = 0; i < DUMP_TABLE_COUNT; ++i) { if (tn == dumpTables[i].name) { type = dumpTables[i].type; break; } } if (i == DUMP_TABLE_COUNT) { TC_LOG_ERROR("misc", "LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } // change the data to server values switch (type) { case DTT_CHARACTER: { if (!changenth(line, 1, newguid)) // characters.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); race = uint8(atol(getnth(line, 4).c_str())); playerClass = uint8(atol(getnth(line, 5).c_str())); gender = uint8(atol(getnth(line, 6).c_str())); level = uint8(atol(getnth(line, 7).c_str())); if (name == "") { // check if the original name already exists name = getnth(line, 3); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, name); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) if (!changenth(line, 38, "1")) // characters.at_login set to "rename on login" ROLLBACK(DUMP_FILE_BROKEN); } else if (!changenth(line, 3, name.c_str())) // characters.name ROLLBACK(DUMP_FILE_BROKEN); const char null[5] = "NULL"; if (!changenth(line, 63, null)) // characters.deleteInfos_Account ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 64, null)) // characters.deleteInfos_Name ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 65, null)) // characters.deleteDate ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_CHAR_TABLE: { if (!changenth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_EQSET_TABLE: { if (!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.guid char newSetGuid[24]; snprintf(newSetGuid, 24, UI64FMTD, sObjectMgr->GenerateEquipmentSetGuid()); if (!changenth(line, 2, newSetGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.setguid break; } case DTT_INVENTORY: { if (!changenth(line, 1, newguid)) // character_inventory.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update if (!changeGuid(line, 4, items, sObjectMgr->_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update break; } case DTT_MAIL: // mail { if (!changeGuid(line, 1, mails, sObjectMgr->_mailId)) ROLLBACK(DUMP_FILE_BROKEN); // mail.id update if (!changenth(line, 6, newguid)) // mail.receiver update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { if (!changeGuid(line, 1, mails, sObjectMgr->_mailId)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid if (!changenth(line, 3, newguid)) // mail_items.receiver ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM: { // item, owner, data field:item, owner guid if (!changeGuid(line, 1, items, sObjectMgr->_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if (!changenth(line, 3, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: { if (!changenth(line, 1, newguid)) // character_gifts.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update break; } case DTT_PET: { //store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if (*lastpetid == '\0') snprintf(lastpetid, 20, "%s", currpetid); if (strcmp(lastpetid, currpetid) != 0) { snprintf(newpetid, 20, "%d", sObjectMgr->GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } if (!changenth(line, 1, newpetid)) // character_pet.id update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, newguid)) // character_pet.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if (!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); break; } default: TC_LOG_ERROR("misc", "Unknown dump table type: %u", type); break; } fixNULLfields(line); trans->Append(line.c_str()); } CharacterDatabase.CommitTransaction(trans); // in case of name conflict player has to rename at login anyway sWorld->AddCharacterNameData(guid, name, gender, race, playerClass, level); sObjectMgr->_hiItemGuid += items.size(); sObjectMgr->_mailId += mails.size(); if (incHighest) ++sObjectMgr->_hiCharGuid; fclose(fin); return DUMP_SUCCESS; }
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { // check character count { QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", account); uint8 charcount = 0; if (result) { Field *fields=result->Fetch(); charcount = fields[0].GetUInt8(); delete result; if (charcount >= 10) return DUMP_TOO_MANY_CHARS; } } FILE *fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; QueryResult * result = NULL; char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid != 0 && guid < objmgr.m_hiCharGuid) { result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%d'", guid); if (result) { guid = objmgr.m_hiCharGuid; // use first free if exists delete result; } else incHighest = false; } else guid = objmgr.m_hiCharGuid; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name = ""; if (ObjectMgr::CheckPlayerName(name,true) == CHAR_NAME_SUCCESS) { CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); if (result) { name = ""; // use the one from the dump delete result; } } else name = ""; // name encoded or empty snprintf(newguid, 20, "%d", guid); snprintf(chraccount, 20, "%d", account); snprintf(newpetid, 20, "%d", objmgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32,uint32> items; std::map<uint32,uint32> mails; std::map<uint32,uint32> itemTexts; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; CharacterDatabase.BeginTransaction(); while(!feof(fin)) { if(!fgets(buf, 32000, fin)) { if(feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if(nw_pos==std::string::npos) continue; // skip NOTE if(line.substr(nw_pos,15)=="IMPORTANT NOTE:") continue; // add required_ check if(line.substr(nw_pos,41)=="UPDATE character_db_version SET required_") { if(!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } // determine table name and load type std::string tn = gettablename(line); if(tn.empty()) { sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type; uint8 i; for(i = 0; i < DUMP_TABLE_COUNT; ++i) { if (tn == dumpTables[i].name) { type = dumpTables[i].type; break; } } if (i == DUMP_TABLE_COUNT) { sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } // change the data to server values switch(type) { case DTT_CHAR_TABLE: if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHARACTER: // character t. { if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // guid, data field:guid, items if(!changenth(line, 2, chraccount)) ROLLBACK(DUMP_FILE_BROKEN); std::string vals = getnth(line, 3); if(!changetoknth(vals, OBJECT_FIELD_GUID+1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); for(uint16 field = PLAYER_FIELD_INV_SLOT_HEAD; field < PLAYER_FARSIGHT; field++) if(!changetokGuid(vals, field+1, items, objmgr.m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 3, vals.c_str())) ROLLBACK(DUMP_FILE_BROKEN); if (name == "") { // check if the original name already exists name = getnth(line, 4); CharacterDatabase.escape_string(name); result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); if (result) { delete result; if(!changenth(line, 37, "1")) // rename on login: `at_login` field 37 in raw field list ROLLBACK(DUMP_FILE_BROKEN); } } else if(!changenth(line, 4, name.c_str())) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_INVENTORY: // character_inventory t. { if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // bag, item if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 4, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM: // item_instance t. { // item, owner, data field:item, owner guid if(!changeGuid(line, 1, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 2, newguid)) ROLLBACK(DUMP_FILE_BROKEN); std::string vals = getnth(line,3); if(!changetokGuid(vals, OBJECT_FIELD_GUID+1, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, objmgr.m_ItemTextId,true)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 3, vals.c_str())) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: // character_gift { // guid,item_guid, if(!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET: // character_pet t { //store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if(strlen(lastpetid)==0) snprintf(lastpetid, 20, "%s", currpetid); if(strcmp(lastpetid,currpetid)!=0) { snprintf(newpetid, 20, "%d", objmgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if(petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } // item, entry, owner, ... if(!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 3, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown t { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if(petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if(!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL: // mail { // id,messageType,stationery,mailtemplate,sender,receiver,subject,itemText if(!changeGuid(line, 1, mails, objmgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 6, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 8, itemTexts, objmgr.m_ItemTextId)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { // mail_id,item_guid,item_template,receiver if(!changeGuid(line, 1, mails, objmgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changeGuid(line, 2, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 4, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_TEXT: // item_text { // id if(!changeGuid(line, 1, itemTexts, objmgr.m_ItemTextId)) ROLLBACK(DUMP_FILE_BROKEN); // add it to cache uint32 id= atoi(getnth(line,1).c_str()); std::string text = getnth(line,2); objmgr.AddItemText(id,text); break; } default: sLog.outError("Unknown dump table type: %u",type); break; } if(!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); } CharacterDatabase.CommitTransaction(); objmgr.m_hiItemGuid += items.size(); objmgr.m_mailid += mails.size(); objmgr.m_ItemTextId += itemTexts.size(); if(incHighest) ++objmgr.m_hiCharGuid; fclose(fin); return DUMP_SUCCESS; }
DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, std::string name, ObjectGuid::LowType guid) { uint32 charcount = AccountMgr::GetCharactersCount(account); if (charcount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)) return DUMP_TOO_MANY_CHARS; FILE* fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; char newguid[20], chraccount[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid && guid < sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed()) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_GUID); stmt->setUInt64(0, guid); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) guid = sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed(); // use first free if exists else incHighest = false; } else guid = sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed(); // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name.clear(); if (ObjectMgr::CheckPlayerName(name, sWorld->GetDefaultDbcLocale(), true) == CHAR_NAME_SUCCESS) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, name); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) name.clear(); // use the one from the dump } else name.clear(); // name encoded or empty snprintf(newguid, 20, UI64FMTD, guid); snprintf(chraccount, 20, "%u", account); DumpGuidMap items; DumpGuidMap mails; char buf[32000] = ""; typedef std::map<uint32 /*old*/, uint32 /*new*/> PetIds; PetIds petIds; uint8 gender = GENDER_NONE; uint8 race = RACE_NONE; uint8 playerClass = 0; uint8 level = 1; ObjectGuid::LowType itemLowGuidOffset = sObjectMgr->GetGenerator<HighGuid::Item>().GetNextAfterMaxUsed(); SQLTransaction trans = CharacterDatabase.BeginTransaction(); while (!feof(fin)) { if (!fgets(buf, 32000, fin)) { if (feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if (nw_pos == std::string::npos) continue; // skip logfile-side dump start notice, the important notes and dump end notices if ((line.substr(nw_pos, 16) == "== START DUMP ==") || (line.substr(nw_pos, 15) == "IMPORTANT NOTE:") || (line.substr(nw_pos, 14) == "== END DUMP ==")) continue; // add required_ check /* if (line.substr(nw_pos, 41) == "UPDATE character_db_version SET required_") { if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } */ // determine table name and load type std::string tn = GetTableName(line); if (tn.empty()) { TC_LOG_ERROR("misc", "LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type = DumpTableType(0); uint8 i; for (i = 0; i < DUMP_TABLE_COUNT; ++i) { if (tn == dumpTables[i].name) { type = dumpTables[i].type; break; } } if (i == DUMP_TABLE_COUNT) { TC_LOG_ERROR("misc", "LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } // change the data to server values switch (type) { case DTT_CHARACTER: { if (!ChangeNth(line, 1, newguid)) // characters.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!ChangeNth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); race = uint8(atoul(GetNth(line, 4).c_str())); playerClass = uint8(atoul(GetNth(line, 5).c_str())); gender = uint8(atoul(GetNth(line, 6).c_str())); level = uint8(atoul(GetNth(line, 7).c_str())); if (name.empty()) { // check if the original name already exists name = GetNth(line, 3); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, name); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) if (!ChangeNth(line, 41, "1")) // characters.at_login set to "rename on login" ROLLBACK(DUMP_FILE_BROKEN); } else if (!ChangeNth(line, 3, name.c_str())) // characters.name ROLLBACK(DUMP_FILE_BROKEN); const char null[5] = "NULL"; if (!ChangeNth(line, 65, null)) // characters.deleteInfos_Account ROLLBACK(DUMP_FILE_BROKEN); if (!ChangeNth(line, 66, null)) // characters.deleteInfos_Name ROLLBACK(DUMP_FILE_BROKEN); if (!ChangeNth(line, 67, null)) // characters.deleteDate ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_CHAR_TABLE: case DTT_CURRENCY: { if (!ChangeNth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_EQSET_TABLE: { if (!ChangeNth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.guid char newSetGuid[24]; snprintf(newSetGuid, 24, UI64FMTD, sObjectMgr->GenerateEquipmentSetGuid()); if (!ChangeNth(line, 2, newSetGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.setguid for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot) if (!ChangeGuid(line, 7 + slot, items, itemLowGuidOffset, true)) ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.item break; } case DTT_INVENTORY: { if (!ChangeNth(line, 1, newguid)) // character_inventory.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!ChangeGuid(line, 2, items, itemLowGuidOffset, true)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update if (!ChangeGuid(line, 4, items, itemLowGuidOffset)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update break; } case DTT_MAIL: // mail { if (!ChangeGuid(line, 1, mails, sObjectMgr->_mailId)) ROLLBACK(DUMP_FILE_BROKEN); // mail.id update if (!ChangeNth(line, 6, newguid)) // mail.receiver update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { if (!ChangeGuid(line, 1, mails, sObjectMgr->_mailId)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id if (!ChangeGuid(line, 2, items, itemLowGuidOffset)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid if (!ChangeNth(line, 3, newguid)) // mail_items.receiver ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM: { // item, owner, data field:item, owner guid if (!ChangeGuid(line, 1, items, itemLowGuidOffset)) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if (!ChangeNth(line, 3, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: { if (!ChangeNth(line, 1, newguid)) // character_gifts.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!ChangeGuid(line, 2, items, itemLowGuidOffset)) ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update break; } case DTT_PET: { // store a map of old pet id to new inserted pet id for use by DTT_PET_TABLE tables std::string petIdStr = GetNth(line, 1); uint32 currentPetId = atoul(petIdStr.c_str()); PetIds::const_iterator petIdsItr = petIds.find(currentPetId); if (petIdsItr != petIds.end()) // duplicate pets ROLLBACK(DUMP_FILE_BROKEN); uint32 newPetId = sObjectMgr->GeneratePetNumber(); petIds[currentPetId] = newPetId; if (!ChangeNth(line, 1, std::to_string(newPetId).c_str())) // character_pet.id update ROLLBACK(DUMP_FILE_BROKEN); if (!ChangeNth(line, 3, newguid)) // character_pet.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown { std::string petIdStr = GetNth(line, 1); // lookup currpetid and match to new inserted pet id PetIds::const_iterator petIdsItr = petIds.find(atoul(petIdStr.c_str())); if (petIdsItr == petIds.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); if (!ChangeNth(line, 1, std::to_string(petIdsItr->second).c_str())) ROLLBACK(DUMP_FILE_BROKEN); break; } default: TC_LOG_ERROR("misc", "Unknown dump table type: %u", type); break; } fixNULLfields(line); trans->Append(line.c_str()); } CharacterDatabase.CommitTransaction(trans); // in case of name conflict player has to rename at login anyway sWorld->AddCharacterInfo(ObjectGuid::Create<HighGuid::Player>(guid), account, name, gender, race, playerClass, level, false); sObjectMgr->GetGenerator<HighGuid::Item>().Set(sObjectMgr->GetGenerator<HighGuid::Item>().GetNextAfterMaxUsed() + items.size()); sObjectMgr->_mailId += mails.size(); if (incHighest) sObjectMgr->GetGenerator<HighGuid::Player>().Generate(); fclose(fin); return DUMP_SUCCESS; }