aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Handlers/CharacterHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Handlers/CharacterHandler.cpp')
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp440
1 files changed, 170 insertions, 270 deletions
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 644365b9177..04477528a04 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -42,6 +42,7 @@
#include "Pet.h"
#include "PlayerDump.h"
#include "Player.h"
+#include "QueryCallback.h"
#include "QueryPackets.h"
#include "ReputationMgr.h"
#include "GitRevision.h"
@@ -350,8 +351,7 @@ void WorldSession::HandleCharEnumOpcode(WorldPackets::Character::EnumCharacters&
stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
stmt->setUInt32(1, GetAccountId());
- _charEnumCallback.SetParam(false);
- _charEnumCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharEnum, this, std::placeholders::_1)));
}
void WorldSession::HandleCharUndeleteEnum(PreparedQueryResult result)
@@ -393,8 +393,7 @@ void WorldSession::HandleCharUndeleteEnumOpcode(WorldPackets::Character::EnumCha
stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
stmt->setUInt32(1, GetAccountId());
- _charEnumCallback.SetParam(true);
- _charEnumCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharUndeleteEnum, this, std::placeholders::_1)));
}
void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharacter& charCreate)
@@ -519,101 +518,60 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact
}
}
+ std::shared_ptr<WorldPackets::Character::CharacterCreateInfo> createInfo = charCreate.CreateInfo;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->setString(0, charCreate.CreateInfo->Name);
- _charCreateCallback.SetParam(charCreate.CreateInfo);
- _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
-}
-
-void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPackets::Character::CharacterCreateInfo* createInfo)
-{
- /** This is a series of callbacks executed consecutively as a result from the database becomes available.
- This is much more efficient than synchronous requests on packet handler, and much less DoS prone.
- It also prevents data synchronisation errors.
- */
- switch (_charCreateCallback.GetStage())
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
{
- case 0:
+ if (result)
{
- if (result)
- {
- SendCharCreate(CHAR_CREATE_NAME_IN_USE);
- _charCreateCallback.Reset();
- return;
- }
-
- ASSERT(_charCreateCallback.GetParam().get() == createInfo);
+ SendCharCreate(CHAR_CREATE_NAME_IN_USE);
+ return;
+ }
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SUM_REALM_CHARACTERS);
- stmt->setUInt32(0, GetAccountId());
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SUM_REALM_CHARACTERS);
+ stmt->setUInt32(0, GetAccountId());
+ queryCallback.SetNextQuery(LoginDatabase.AsyncQuery(stmt));
+ })
+ .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
+ {
+ uint64 acctCharCount = 0;
+ if (result)
+ {
+ Field* fields = result->Fetch();
+ acctCharCount = uint64(fields[0].GetDouble());
+ }
- _charCreateCallback.FreeResult();
- _charCreateCallback.SetFutureResult(LoginDatabase.AsyncQuery(stmt));
- _charCreateCallback.NextStage();
- break;
+ if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT))
+ {
+ SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
+ return;
}
- case 1:
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
+ stmt->setUInt32(0, GetAccountId());
+ queryCallback.SetNextQuery(LoginDatabase.AsyncQuery(stmt));
+ })
+ .WithChainingPreparedCallback([this, createInfo](QueryCallback& queryCallback, PreparedQueryResult result)
+ {
+ if (result)
{
- uint64 acctCharCount = 0;
- if (result)
- {
- Field* fields = result->Fetch();
- acctCharCount = uint64(fields[0].GetDouble());
- }
+ Field* fields = result->Fetch();
+ createInfo->CharCount = uint8(fields[0].GetUInt64()); // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
- if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT))
+ if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
{
- SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
- _charCreateCallback.Reset();
+ SendCharCreate(CHAR_CREATE_SERVER_LIMIT);
return;
}
-
- ASSERT(_charCreateCallback.GetParam().get() == createInfo);
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
- stmt->setUInt32(0, GetAccountId());
-
- _charCreateCallback.FreeResult();
- _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
- _charCreateCallback.NextStage();
- break;
}
- case 2:
- {
- if (result)
- {
- Field* fields = result->Fetch();
- createInfo->CharCount = uint8(fields[0].GetUInt64()); // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
- if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
- {
- SendCharCreate(CHAR_CREATE_SERVER_LIMIT);
- _charCreateCallback.Reset();
- return;
- }
- }
-
- bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
- uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
-
- _charCreateCallback.FreeResult();
-
- if (!allowTwoSideAccounts || skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT || createInfo->Class == CLASS_DEMON_HUNTER)
- {
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO);
- stmt->setUInt32(0, GetAccountId());
- stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT || createInfo->Class == CLASS_DEMON_HUNTER) ? 12 : 1);
- _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
- _charCreateCallback.NextStage();
- return;
- }
+ bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
+ uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
- _charCreateCallback.NextStage();
- HandleCharCreateCallback(PreparedQueryResult(NULL), createInfo); // Will jump to case 3
- break;
- }
- case 3:
+ std::function<void(PreparedQueryResult)> finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result)
{
bool haveSameRace = false;
uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
@@ -632,7 +590,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
uint32 freeDemonHunterSlots = sWorld->getIntConfig(CONFIG_DEMON_HUNTERS_PER_REALM);
Field* field = result->Fetch();
- uint8 accRace = field[1].GetUInt8();
+ uint8 accRace = field[1].GetUInt8();
if (checkHeroicReqs)
{
@@ -645,7 +603,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
if (freeHeroicSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
- _charCreateCallback.Reset();
return;
}
}
@@ -669,7 +626,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
if (freeDemonHunterSlots == 0)
{
SendCharCreate(CHAR_CREATE_FAILED);
- _charCreateCallback.Reset();
return;
}
}
@@ -693,7 +649,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
if (accTeam != team)
{
SendCharCreate(CHAR_CREATE_PVP_TEAMS_VIOLATION);
- _charCreateCallback.Reset();
return;
}
}
@@ -722,7 +677,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
if (freeHeroicSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
- _charCreateCallback.Reset();
return;
}
}
@@ -746,7 +700,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
if (freeDemonHunterSlots == 0)
{
SendCharCreate(CHAR_CREATE_FAILED);
- _charCreateCallback.Reset();
return;
}
}
@@ -764,26 +717,23 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
if (checkHeroicReqs && !hasHeroicReqLevel)
{
SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
- _charCreateCallback.Reset();
return;
}
if (checkDemonHunterReqs && !hasDemonHunterReqLevel)
{
SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
- _charCreateCallback.Reset();
return;
}
Player newChar(this);
newChar.GetMotionMaster()->Initialize();
- if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo))
+ if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo.get()))
{
// Player not create (race/class/etc problem?)
newChar.CleanupsBeforeDelete();
SendCharCreate(CHAR_CREATE_ERROR);
- _charCreateCallback.Reset();
return;
}
@@ -792,7 +742,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
newChar.SetAtLoginFlag(AT_LOGIN_FIRST); // First login
- // Player created, save it now
+ // Player created, save it now
newChar.SaveToDB(true);
createInfo->CharCount += 1;
@@ -837,10 +787,19 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac
sWorld->AddCharacterInfo(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER), newChar.getRace(), newChar.getClass(), newChar.getLevel(), false);
newChar.CleanupsBeforeDelete();
- _charCreateCallback.Reset();
- break;
+ };
+
+ if (allowTwoSideAccounts && !skipCinematics && createInfo->Class != CLASS_DEATH_KNIGHT && createInfo->Class != CLASS_DEMON_HUNTER)
+ {
+ finalizeCharacterCreation(PreparedQueryResult(nullptr));
+ return;
}
- }
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO);
+ stmt->setUInt32(0, GetAccountId());
+ stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT || createInfo->Class == CLASS_DEMON_HUNTER) ? 12 : 1);
+ queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
+ }));
}
void WorldSession::HandleCharDeleteOpcode(WorldPackets::Character::CharDelete& charDelete)
@@ -1371,17 +1330,15 @@ void WorldSession::HandleCharRenameOpcode(WorldPackets::Character::CharacterRena
stmt->setUInt64(0, request.RenameInfo->Guid.GetCounter());
stmt->setString(1, request.RenameInfo->NewName);
- _charRenameCallback.SetParam(request.RenameInfo);
- _charRenameCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback(std::bind(&WorldSession::HandleCharRenameCallBack, this, request.RenameInfo, std::placeholders::_1)));
}
-void WorldSession::HandleCharRenameCallBack(PreparedQueryResult result, WorldPackets::Character::CharacterRenameInfo* renameInfo)
+void WorldSession::HandleCharRenameCallBack(std::shared_ptr<WorldPackets::Character::CharacterRenameInfo> renameInfo, PreparedQueryResult result)
{
- ASSERT(_charRenameCallback.GetParam().get() == renameInfo);
-
if (!result)
{
- SendCharRename(CHAR_CREATE_ERROR, renameInfo);
+ SendCharRename(CHAR_CREATE_ERROR, renameInfo.get());
return;
}
@@ -1392,7 +1349,7 @@ void WorldSession::HandleCharRenameCallBack(PreparedQueryResult result, WorldPac
if (!(atLoginFlags & AT_LOGIN_RENAME))
{
- SendCharRename(CHAR_CREATE_ERROR, renameInfo);
+ SendCharRename(CHAR_CREATE_ERROR, renameInfo.get());
return;
}
@@ -1420,7 +1377,7 @@ void WorldSession::HandleCharRenameCallBack(PreparedQueryResult result, WorldPac
TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (%s) Changed name to: %s",
GetAccountId(), GetRemoteAddress().c_str(), oldName.c_str(), renameInfo->Guid.ToString().c_str(), renameInfo->NewName.c_str());
- SendCharRename(RESPONSE_SUCCESS, renameInfo);
+ SendCharRename(RESPONSE_SUCCESS, renameInfo.get());
sWorld->UpdateCharacterInfo(renameInfo->Guid, renameInfo->NewName);
}
@@ -1582,17 +1539,15 @@ void WorldSession::HandleCharCustomizeOpcode(WorldPackets::Character::CharCustom
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO);
stmt->setUInt64(0, packet.CustomizeInfo->CharGUID.GetCounter());
- _charCustomizeCallback.SetParam(packet.CustomizeInfo);
- _charCustomizeCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback(std::bind(&WorldSession::HandleCharCustomizeCallback, this, packet.CustomizeInfo, std::placeholders::_1)));
}
-void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, WorldPackets::Character::CharCustomizeInfo* customizeInfo)
+void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<WorldPackets::Character::CharCustomizeInfo> customizeInfo, PreparedQueryResult result)
{
- ASSERT(_charCustomizeCallback.GetParam().get() == customizeInfo);
-
if (!result)
{
- SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo);
+ SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
return;
}
@@ -1607,13 +1562,13 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World
if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo->HairStyleID, customizeInfo->HairColorID, customizeInfo->FaceID,
customizeInfo->FacialHairStyleID, customizeInfo->SkinID, customizeInfo->CustomDisplay))
{
- SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo);
+ SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
return;
}
if (!(atLoginFlags & AT_LOGIN_CUSTOMIZE))
{
- SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo);
+ SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
return;
}
@@ -1622,21 +1577,21 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World
// prevent character rename to invalid name
if (!normalizePlayerName(customizeInfo->CharName))
{
- SendCharCustomize(CHAR_NAME_NO_NAME, customizeInfo);
+ SendCharCustomize(CHAR_NAME_NO_NAME, customizeInfo.get());
return;
}
ResponseCodes res = ObjectMgr::CheckPlayerName(customizeInfo->CharName, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
- SendCharCustomize(res, customizeInfo);
+ SendCharCustomize(res, customizeInfo.get());
return;
}
// check name limitations
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(customizeInfo->CharName))
{
- SendCharCustomize(CHAR_NAME_RESERVED, customizeInfo);
+ SendCharCustomize(CHAR_NAME_RESERVED, customizeInfo.get());
return;
}
@@ -1647,7 +1602,7 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World
{
if (newGuid != customizeInfo->CharGUID)
{
- SendCharCustomize(CHAR_CREATE_NAME_IN_USE, customizeInfo);
+ SendCharCustomize(CHAR_CREATE_NAME_IN_USE, customizeInfo.get());
return;
}
}
@@ -1694,7 +1649,7 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World
sWorld->UpdateCharacterInfo(customizeInfo->CharGUID, customizeInfo->CharName, customizeInfo->SexID);
- SendCharCustomize(RESPONSE_SUCCESS, customizeInfo);
+ SendCharCustomize(RESPONSE_SUCCESS, customizeInfo.get());
TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s), Character[%s] (%s) Customized to: %s",
GetAccountId(), GetRemoteAddress().c_str(), oldName.c_str(), customizeInfo->CharGUID.ToString().c_str(), customizeInfo->CharName.c_str());
@@ -1855,17 +1810,15 @@ void WorldSession::HandleCharRaceOrFactionChangeOpcode(WorldPackets::Character::
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS);
stmt->setUInt64(0, packet.RaceOrFactionChangeInfo->Guid.GetCounter());
- _charFactionChangeCallback.SetParam(packet.RaceOrFactionChangeInfo);
- _charFactionChangeCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback(std::bind(&WorldSession::HandleCharRaceOrFactionChangeCallback, this, packet.RaceOrFactionChangeInfo, std::placeholders::_1)));
}
-void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult result, WorldPackets::Character::CharRaceOrFactionChangeInfo* factionChangeInfo)
+void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPackets::Character::CharRaceOrFactionChangeInfo> factionChangeInfo, PreparedQueryResult result)
{
- ASSERT(_charFactionChangeCallback.GetParam().get() == factionChangeInfo);
-
if (!result)
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
@@ -1873,7 +1826,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(factionChangeInfo->Guid);
if (!characterInfo)
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
@@ -1883,7 +1836,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
if (!sObjectMgr->GetPlayerInfo(factionChangeInfo->RaceID, playerClass))
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
@@ -1894,20 +1847,20 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
uint16 usedLoginFlag = (factionChangeInfo->FactionChange ? AT_LOGIN_CHANGE_FACTION : AT_LOGIN_CHANGE_RACE);
if (!(atLoginFlags & usedLoginFlag))
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
TeamId newTeamId = Player::TeamIdForRace(factionChangeInfo->RaceID);
if (newTeamId == TEAM_NEUTRAL)
{
- SendCharFactionChange(CHAR_CREATE_RESTRICTED_RACECLASS, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_RESTRICTED_RACECLASS, factionChangeInfo.get());
return;
}
if (factionChangeInfo->FactionChange == (Player::TeamIdForRace(oldRace) == newTeamId))
{
- SendCharFactionChange(factionChangeInfo->FactionChange ? CHAR_CREATE_CHARACTER_SWAP_FACTION : CHAR_CREATE_CHARACTER_RACE_ONLY, factionChangeInfo);
+ SendCharFactionChange(factionChangeInfo->FactionChange ? CHAR_CREATE_CHARACTER_SWAP_FACTION : CHAR_CREATE_CHARACTER_RACE_ONLY, factionChangeInfo.get());
return;
}
@@ -1916,7 +1869,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
if ((1 << (factionChangeInfo->RaceID - 1)) & raceMaskDisabled)
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
}
@@ -1924,21 +1877,21 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
// prevent character rename to invalid name
if (!normalizePlayerName(factionChangeInfo->Name))
{
- SendCharFactionChange(CHAR_NAME_NO_NAME, factionChangeInfo);
+ SendCharFactionChange(CHAR_NAME_NO_NAME, factionChangeInfo.get());
return;
}
ResponseCodes res = ObjectMgr::CheckPlayerName(factionChangeInfo->Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
- SendCharFactionChange(res, factionChangeInfo);
+ SendCharFactionChange(res, factionChangeInfo.get());
return;
}
// check name limitations
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(factionChangeInfo->Name))
{
- SendCharFactionChange(CHAR_NAME_RESERVED, factionChangeInfo);
+ SendCharFactionChange(CHAR_NAME_RESERVED, factionChangeInfo.get());
return;
}
@@ -1948,14 +1901,14 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
{
if (newGuid != factionChangeInfo->Guid)
{
- SendCharFactionChange(CHAR_CREATE_NAME_IN_USE, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_NAME_IN_USE, factionChangeInfo.get());
return;
}
}
if (sArenaTeamMgr->GetArenaTeamByCaptain(factionChangeInfo->Guid))
{
- SendCharFactionChange(CHAR_CREATE_CHARACTER_ARENA_LEADER, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_CHARACTER_ARENA_LEADER, factionChangeInfo.get());
return;
}
@@ -2306,7 +2259,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
if (tokens.size() != ktcount)
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
@@ -2370,7 +2323,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
TC_LOG_DEBUG("entities.player", "%s (IP: %s) changed race from %u to %u", GetPlayerInfo().c_str(), GetRemoteAddress().c_str(), oldRace, factionChangeInfo->RaceID);
- SendCharFactionChange(RESPONSE_SUCCESS, factionChangeInfo);
+ SendCharFactionChange(RESPONSE_SUCCESS, factionChangeInfo.get());
}
void WorldSession::HandleRandomizeCharNameOpcode(WorldPackets::Character::GenerateRandomCharacterName& packet)
@@ -2427,176 +2380,123 @@ void WorldSession::HandleOpeningCinematic(WorldPackets::Misc::OpeningCinematic&
void WorldSession::HandleGetUndeleteCooldownStatus(WorldPackets::Character::GetUndeleteCharacterCooldownStatus& /*getCooldown*/)
{
- /// empty result to force wait
- PreparedQueryResultPromise result;
- result.set_value(PreparedQueryResult(nullptr));
- _undeleteCooldownStatusCallback.SetFutureResult(result.get_future());
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LAST_CHAR_UNDELETE);
+ stmt->setUInt32(0, GetBattlenetAccountId());
+
+ _queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleUndeleteCooldownStatusCallback, this, std::placeholders::_1)));
}
void WorldSession::HandleUndeleteCooldownStatusCallback(PreparedQueryResult result)
{
- switch (_undeleteCooldownStatusCallback.GetStage())
+ uint32 cooldown = 0;
+ uint32 maxCooldown = sWorld->getIntConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_COOLDOWN);
+ if (result)
{
- case 0:
- {
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LAST_CHAR_UNDELETE);
- stmt->setUInt32(0, GetBattlenetAccountId());
-
- _undeleteCooldownStatusCallback.FreeResult();
- _undeleteCooldownStatusCallback.SetFutureResult(LoginDatabase.AsyncQuery(stmt));
- _undeleteCooldownStatusCallback.NextStage();
- break;
- }
- case 1:
- {
- uint32 cooldown = 0;
- uint32 maxCooldown = sWorld->getIntConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_COOLDOWN);
- if (result)
- {
- uint32 lastUndelete = result->Fetch()[0].GetUInt32();
- uint32 now = uint32(time(nullptr));
- if (lastUndelete + maxCooldown > now)
- cooldown = std::max<uint32>(0, lastUndelete + maxCooldown - now);
- }
-
- SendUndeleteCooldownStatusResponse(cooldown, maxCooldown);
- _undeleteCooldownStatusCallback.Reset();
- break;
- }
+ uint32 lastUndelete = result->Fetch()[0].GetUInt32();
+ uint32 now = uint32(time(nullptr));
+ if (lastUndelete + maxCooldown > now)
+ cooldown = std::max<uint32>(0, lastUndelete + maxCooldown - now);
}
+ SendUndeleteCooldownStatusResponse(cooldown, maxCooldown);
}
-void WorldSession::HandleCharUndeleteOpcode(WorldPackets::Character::UndeleteCharacter& undeleteInfo)
+void WorldSession::HandleCharUndeleteOpcode(WorldPackets::Character::UndeleteCharacter& undeleteCharacter)
{
if (!sWorld->getBoolConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_ENABLED))
{
- SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_DISABLED, undeleteInfo.UndeleteInfo.get());
+ SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_DISABLED, undeleteCharacter.UndeleteInfo.get());
return;
}
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LAST_CHAR_UNDELETE);
stmt->setUInt32(0, GetBattlenetAccountId());
- _charUndeleteCallback.SetParam(undeleteInfo.UndeleteInfo);
- _charUndeleteCallback.SetFutureResult(LoginDatabase.AsyncQuery(stmt));
- _charUndeleteCallback.NextStage();
-}
-
-void WorldSession::HandleCharUndeleteCallback(PreparedQueryResult result, WorldPackets::Character::CharacterUndeleteInfo* undeleteInfo)
-{
- /** This is a series of callbacks executed consecutively as a result from the database becomes available.
- * This is much more efficient than synchronous requests on packet handler.
- * It also prevents data synchronisation errors.
- */
-
- ASSERT(_charUndeleteCallback.GetParam().get() == undeleteInfo);
-
- switch (_charUndeleteCallback.GetStage())
+ std::shared_ptr<WorldPackets::Character::CharacterUndeleteInfo> undeleteInfo = undeleteCharacter.UndeleteInfo;
+ _queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt)
+ .WithChainingPreparedCallback([this, undeleteInfo](QueryCallback& queryCallback, PreparedQueryResult result)
{
- case 1:
- {
- if (result)
- {
- uint32 lastUndelete = result->Fetch()[0].GetUInt32();
- uint32 maxCooldown = sWorld->getIntConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_COOLDOWN);
- if (lastUndelete && (lastUndelete + maxCooldown > time(nullptr)))
- {
- SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_COOLDOWN, undeleteInfo);
- _charUndeleteCallback.Reset();
- return;
- }
- }
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID);
- stmt->setUInt64(0, undeleteInfo->CharacterGuid.GetCounter());
-
- _charUndeleteCallback.FreeResult();
- _charUndeleteCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
- _charUndeleteCallback.NextStage();
- break;
- }
- case 2:
+ if (result)
{
- if (!result)
+ uint32 lastUndelete = result->Fetch()[0].GetUInt32();
+ uint32 maxCooldown = sWorld->getIntConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_COOLDOWN);
+ if (lastUndelete && (lastUndelete + maxCooldown > time(nullptr)))
{
- SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_CHAR_CREATE, undeleteInfo);
- _charUndeleteCallback.Reset();
+ SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_COOLDOWN, undeleteInfo.get());
return;
}
+ }
- Field* fields = result->Fetch();
- undeleteInfo->Name = fields[1].GetString();
- uint32 account = fields[2].GetUInt32();
-
- if (account != GetAccountId())
- {
- SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_UNKNOWN, undeleteInfo);
- _charUndeleteCallback.Reset();
- return;
- }
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID);
+ stmt->setUInt64(0, undeleteInfo->CharacterGuid.GetCounter());
+ queryCallback.SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
+ })
+ .WithChainingPreparedCallback([this, undeleteInfo](QueryCallback& queryCallback, PreparedQueryResult result)
+ {
+ if (!result)
+ {
+ SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_CHAR_CREATE, undeleteInfo.get());
+ return;
+ }
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
- stmt->setString(0, undeleteInfo->Name);
+ Field* fields = result->Fetch();
+ undeleteInfo->Name = fields[1].GetString();
+ uint32 account = fields[2].GetUInt32();
- _charUndeleteCallback.FreeResult();
- _charUndeleteCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
- _charUndeleteCallback.NextStage();
- break;
- }
- case 3:
+ if (account != GetAccountId())
{
- if (result)
- {
- SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_NAME_TAKEN_BY_THIS_ACCOUNT, undeleteInfo);
- _charUndeleteCallback.Reset();
- return;
- }
+ SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_UNKNOWN, undeleteInfo.get());
+ return;
+ }
- /// @todo: add more safety checks
- /// * max char count per account
- /// * max heroic char count
- /// * team violation
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
+ stmt->setString(0, undeleteInfo->Name);
+ queryCallback.SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
+ })
+ .WithChainingPreparedCallback([this, undeleteInfo](QueryCallback& queryCallback, PreparedQueryResult result)
+ {
+ if (result)
+ {
+ SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_NAME_TAKEN_BY_THIS_ACCOUNT, undeleteInfo.get());
+ return;
+ }
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
- stmt->setUInt32(0, GetAccountId());
+ /// @todo: add more safety checks
+ /// * max char count per account
+ /// * max heroic char count
+ /// * team violation
- _charUndeleteCallback.FreeResult();
- _charUndeleteCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
- _charUndeleteCallback.NextStage();
- break;
- }
- case 4:
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
+ stmt->setUInt32(0, GetAccountId());
+ queryCallback.SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
+ })
+ .WithPreparedCallback([this, undeleteInfo](PreparedQueryResult result)
+ {
+ if (result)
{
- if (result)
- {
- Field* fields = result->Fetch();
+ Field* fields = result->Fetch();
- if (fields[0].GetUInt64() >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)) // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
- {
- SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_CHAR_CREATE, undeleteInfo);
- _charUndeleteCallback.Reset();
- return;
- }
+ if (fields[0].GetUInt64() >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)) // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
+ {
+ SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_ERROR_CHAR_CREATE, undeleteInfo.get());
+ return;
}
+ }
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_RESTORE_DELETE_INFO);
- stmt->setString(0, undeleteInfo->Name);
- stmt->setUInt32(1, GetAccountId());
- stmt->setUInt64(2, undeleteInfo->CharacterGuid.GetCounter());
- CharacterDatabase.Execute(stmt);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_RESTORE_DELETE_INFO);
+ stmt->setString(0, undeleteInfo->Name);
+ stmt->setUInt32(1, GetAccountId());
+ stmt->setUInt64(2, undeleteInfo->CharacterGuid.GetCounter());
+ CharacterDatabase.Execute(stmt);
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_CHAR_UNDELETE);
- stmt->setUInt32(0, GetBattlenetAccountId());
- LoginDatabase.Execute(stmt);
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_CHAR_UNDELETE);
+ stmt->setUInt32(0, GetBattlenetAccountId());
+ LoginDatabase.Execute(stmt);
- sWorld->UpdateCharacterInfoDeleted(undeleteInfo->CharacterGuid, false, &undeleteInfo->Name);
+ sWorld->UpdateCharacterInfoDeleted(undeleteInfo->CharacterGuid, false, &undeleteInfo->Name);
- SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_OK, undeleteInfo);
- _charUndeleteCallback.Reset();
- break;
- }
- }
+ SendUndeleteCharacterResponse(CHARACTER_UNDELETE_RESULT_OK, undeleteInfo.get());
+ }));
}
void WorldSession::SendCharCreate(ResponseCodes result)