diff options
Diffstat (limited to 'src/server/game/Handlers/CharacterHandler.cpp')
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 287 |
1 files changed, 233 insertions, 54 deletions
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index f1ec017962e..cdc6ef1f2cb 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -26,6 +26,7 @@ #include "DatabaseEnv.h" #include "Group.h" #include "Guild.h" +#include "GuildFinderMgr.h" #include "GuildMgr.h" #include "Language.h" #include "LFGMgr.h" @@ -47,7 +48,6 @@ #include "WorldPacket.h" #include "WorldSession.h" - class LoginQueryHolder : public SQLQueryHolder { private: @@ -116,6 +116,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt32(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_INVENTORY, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_VOID_STORAGE); + stmt->setUInt32(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS); stmt->setUInt32(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_ACTIONS, stmt); @@ -168,6 +172,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt32(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUF_PROFILES); + stmt->setUInt32(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BGDATA); stmt->setUInt32(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_BG_DATA, stmt); @@ -204,36 +212,53 @@ bool LoginQueryHolder::Initialize() stmt->setUInt32(0, m_accountId); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_CURRENCY); + stmt->setUInt32(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CURRENCY, stmt); + return res; } void WorldSession::HandleCharEnum(PreparedQueryResult result) { - WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size + uint32 charCount = 0; + ByteBuffer bitBuffer; + ByteBuffer dataBuffer; - uint8 num = 0; - - data << num; - - _legitCharacters.clear(); + bitBuffer.WriteBits(0, 23); + bitBuffer.WriteBit(1); if (result) { + _legitCharacters.clear(); + + charCount = uint32(result->GetRowCount()); + bitBuffer.reserve(24 * charCount / 8); + dataBuffer.reserve(charCount * 381); + + bitBuffer.WriteBits(charCount, 17); + do { - uint32 guidlow = (*result)[0].GetUInt32(); - sLog->outInfo(LOG_FILTER_NETWORKIO, "Loading char guid %u from account %u.", guidlow, GetAccountId()); - if (Player::BuildEnumData(result, &data)) - { - _legitCharacters.insert(guidlow); - if (!sWorld->HasCharacterNameData(guidlow)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. - sWorld->AddCharacterNameData(guidlow, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8()); - ++num; - } - } - while (result->NextRow()); + uint32 guidLow = (*result)[0].GetUInt32(); + + sLog->outInfo(LOG_FILTER_NETWORKIO, "Loading char guid %u from account %u.", guidLow, GetAccountId()); + + Player::BuildEnumData(result, &dataBuffer, &bitBuffer); + + _legitCharacters.insert(guidLow); + if (!sWorld->HasCharacterNameData(guidLow)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. + sWorld->AddCharacterNameData(guidLow, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8()); + } while (result->NextRow()); + + bitBuffer.FlushBits(); } + else + bitBuffer.WriteBits(0, 17); - data.put<uint8>(0, num); + WorldPacket data(SMSG_CHAR_ENUM, 7 + bitBuffer.size() + dataBuffer.size()); + data.append(bitBuffer); + if (charCount) + data.append(dataBuffer); SendPacket(&data); } @@ -747,6 +772,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) sLog->outCharDump(dump.c_str(), accountId, GUID_LOPART(guid), name.c_str()); } + sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(guid); sCalendarMgr->RemoveAllPlayerEventsAndInvites(guid); Player::DeleteFromDB(guid, accountId); @@ -759,16 +785,33 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData) { if (PlayerLoading() || GetPlayer() != NULL) { - sLog->outError(LOG_FILTER_NETWORKIO, "Player tryes to login again, AccountId = %d", GetAccountId()); + sLog->outError(LOG_FILTER_NETWORKIO, "Player tries to login again, AccountId = %d", GetAccountId()); return; } m_playerLoading = true; - uint64 playerGuid = 0; + ObjectGuid playerGuid; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd Player Logon Message"); - - recvData >> playerGuid; + playerGuid[2] = recvData.ReadBit(); + playerGuid[3] = recvData.ReadBit(); + playerGuid[0] = recvData.ReadBit(); + playerGuid[6] = recvData.ReadBit(); + playerGuid[4] = recvData.ReadBit(); + playerGuid[5] = recvData.ReadBit(); + playerGuid[1] = recvData.ReadBit(); + playerGuid[7] = recvData.ReadBit(); + + recvData.ReadByteSeq(playerGuid[2]); + recvData.ReadByteSeq(playerGuid[7]); + recvData.ReadByteSeq(playerGuid[0]); + recvData.ReadByteSeq(playerGuid[3]); + recvData.ReadByteSeq(playerGuid[5]); + recvData.ReadByteSeq(playerGuid[6]); + recvData.ReadByteSeq(playerGuid[1]); + recvData.ReadByteSeq(playerGuid[4]); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "Character (Guid: %u) logging in", GUID_LOPART(playerGuid)); if (!IsLegitCharacterForAccount(GUID_LOPART(playerGuid))) { @@ -788,6 +831,17 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData) _charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder); } +void WorldSession::HandleLoadScreenOpcode(WorldPacket& recvPacket) +{ + sLog->outInfo(LOG_FILTER_GENERAL, "WORLD: Recvd CMSG_LOAD_SCREEN"); + uint32 mapID; + + recvPacket >> mapID; + recvPacket.ReadBit(); + + // TODO: Do something with this packet +} + void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) { uint64 playerGuid = holder->GetGuid(); @@ -822,9 +876,34 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) LoadAccountData(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ACCOUNT_DATA), PER_CHARACTER_CACHE_MASK); SendAccountDataTimes(PER_CHARACTER_CACHE_MASK); - data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 + bool featureBit4 = true; + data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 7); // checked in 4.2.2 data << uint8(2); // unknown value - data << uint8(0); // enable(1)/disable(0) voice chat interface in client + data << uint32(1); + data << uint32(1); + data << uint32(2); + data << uint32(0); + data.WriteBit(1); + data.WriteBit(1); + data.WriteBit(0); + data.WriteBit(featureBit4); + data.WriteBit(0); + data.WriteBit(0); + data.FlushBits(); + if (featureBit4) + { + data << uint32(1); + data << uint32(0); + data << uint32(10); + data << uint32(60); + } + + //if (featureBit5) + //{ + // data << uint32(0); + // data << uint32(0); + // data << uint32(0); + //} SendPacket(&data); // Send MOTD @@ -871,28 +950,30 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) Field* fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt8()); + if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId())) + pCurrChar->SetGuildLevel(guild->GetLevel()); } else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); + pCurrChar->SetGuildLevel(0); } - if (pCurrChar->GetGuildId() != 0) + data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4); + data << uint64(0); + SendPacket(&data); + + data.Initialize(SMSG_HOTFIX_INFO); + HotfixData const& hotfix = sObjectMgr->GetHotfixData(); + data.WriteBits(hotfix.size(), 22); + data.FlushBits(); + for (uint32 i = 0; i < hotfix.size(); ++i) { - if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId())) - guild->SendLoginInfo(this); - else - { - // remove wrong guild data - sLog->outError(LOG_FILTER_NETWORKIO, "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName().c_str(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId()); - pCurrChar->SetInGuild(0); - } + data << uint32(hotfix[i].Type); + data << uint32(hotfix[i].Timestamp); + data << uint32(hotfix[i].Entry); } - - data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4); - data << uint32(0); - data << uint32(0); SendPacket(&data); pCurrChar->SendInitialPacketsBeforeAddToMap(); @@ -927,18 +1008,26 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) sObjectAccessor->AddObject(pCurrChar); //sLog->outDebug("Player %s added to Map.", pCurrChar->GetName().c_str()); + if (pCurrChar->GetGuildId() != 0) + { + if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId())) + guild->SendLoginInfo(this); + else + { + // remove wrong guild data + sLog->outError(LOG_FILTER_GENERAL, "Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName().c_str(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId()); + pCurrChar->SetInGuild(0); + } + } + pCurrChar->SendInitialPacketsAfterAddToMap(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ONLINE); - stmt->setUInt32(0, pCurrChar->GetGUIDLow()); - CharacterDatabase.Execute(stmt); stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_ONLINE); - stmt->setUInt32(0, GetAccountId()); - LoginDatabase.Execute(stmt); pCurrChar->SetInGameTime(getMSTime()); @@ -965,7 +1054,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) - pCurrChar->SetMovement(MOVE_WATER_WALK); + pCurrChar->SendMovementSetWaterWalking(true); } pCurrChar->ContinueTaxiFlight(); @@ -993,7 +1082,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { - pCurrChar->resetTalents(true); + pCurrChar->ResetTalents(true); pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state SendNotification(LANG_RESET_TALENTS); } @@ -1060,13 +1149,13 @@ void WorldSession::HandleTutorialFlag(WorldPacket& recvData) SetTutorialInt(index, flag); } -void WorldSession::HandleTutorialClear(WorldPacket & /*recvData*/) +void WorldSession::HandleTutorialClear(WorldPacket& /*recvData*/) { for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) SetTutorialInt(i, 0xFFFFFFFF); } -void WorldSession::HandleTutorialReset(WorldPacket & /*recvData*/) +void WorldSession::HandleTutorialReset(WorldPacket& /*recvData*/) { for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) SetTutorialInt(i, 0x00000000); @@ -1340,8 +1429,8 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData) // 0 - ok // 1, 3 - not enough money - // 2 - you have to seat on barber chair - if (!_player->HasEnoughMoney(cost)) + // 2 - you have to sit on barber chair + if (!_player->HasEnoughMoney((uint64)cost)) { WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); data << uint32(1); // no money @@ -1355,7 +1444,7 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData) SendPacket(&data); } - _player->ModifyMoney(-int32(cost)); // it isn't free + _player->ModifyMoney(-int64(cost)); // it isn't free _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost); _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id)); @@ -1380,7 +1469,7 @@ void WorldSession::HandleRemoveGlyph(WorldPacket& recvData) return; } - if (uint32 glyph = _player->GetGlyph(slot)) + if (uint32 glyph = _player->GetGlyph(_player->GetActiveSpec(), slot)) { if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph)) { @@ -1412,9 +1501,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData) recvData >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AT_LOGIN); - stmt->setUInt32(0, GUID_LOPART(guid)); - // TODO: Make async with callback PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) @@ -1516,7 +1603,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData) SendPacket(&data); } -void WorldSession::HandleEquipmentSetSave(WorldPacket &recvData) +void WorldSession::HandleEquipmentSetSave(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_EQUIPMENT_SET_SAVE"); @@ -1578,7 +1665,7 @@ void WorldSession::HandleEquipmentSetDelete(WorldPacket &recvData) _player->DeleteEquipmentSet(setGuid); } -void WorldSession::HandleEquipmentSetUse(WorldPacket &recvData) +void WorldSession::HandleEquipmentSetUse(WorldPacket& recvData) { if (_player->isInCombat()) return; @@ -1781,6 +1868,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) case RACE_UNDEAD_PLAYER: case RACE_TROLL: case RACE_BLOODELF: + case RACE_GOBLIN: team = TEAM_HORDE; break; default: @@ -1825,6 +1913,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) case RACE_NIGHTELF: stmt->setUInt16(1, 113); break; + case RACE_WORGEN: + stmt->setUInt16(1, 791); + break; case RACE_UNDEAD_PLAYER: stmt->setUInt16(1, 673); break; @@ -1837,6 +1928,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) case RACE_BLOODELF: stmt->setUInt16(1, 137); break; + case RACE_GOBLIN: + stmt->setUInt16(1, 792); + break; } trans->Append(stmt); @@ -2179,3 +2273,88 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) data << uint8(race); SendPacket(&data); } + +void WorldSession::HandleRandomizeCharNameOpcode(WorldPacket& recvData) +{ + uint8 gender, race; + + recvData >> race; + recvData >> gender; + + if (!Player::IsValidRace(race)) + { + sLog->outError(LOG_FILTER_GENERAL, "Invalid race (%u) sent by accountId: %u", race, GetAccountId()); + return; + } + + if (!Player::IsValidGender(gender)) + { + sLog->outError(LOG_FILTER_GENERAL, "Invalid gender (%u) sent by accountId: %u", gender, GetAccountId()); + return; + } + + std::string const* name = GetRandomCharacterName(race, gender); + WorldPacket data(SMSG_RANDOMIZE_CHAR_NAME, 10); + data.WriteBit(0); // unk + data.WriteBits(name->size(), 7); + data.WriteString(*name); + SendPacket(&data); +} + +void WorldSession::HandleReorderCharacters(WorldPacket& recvData) +{ + uint32 charactersCount = recvData.ReadBits(10); + + std::vector<ObjectGuid> guids(charactersCount); + uint8 position; + + for (uint8 i = 0; i < charactersCount; ++i) + { + guids[i][1] = recvData.ReadBit(); + guids[i][4] = recvData.ReadBit(); + guids[i][5] = recvData.ReadBit(); + guids[i][3] = recvData.ReadBit(); + guids[i][0] = recvData.ReadBit(); + guids[i][7] = recvData.ReadBit(); + guids[i][6] = recvData.ReadBit(); + guids[i][2] = recvData.ReadBit(); + } + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + for (uint8 i = 0; i < charactersCount; ++i) + { + recvData.ReadByteSeq(guids[i][6]); + recvData.ReadByteSeq(guids[i][5]); + recvData.ReadByteSeq(guids[i][1]); + recvData.ReadByteSeq(guids[i][4]); + recvData.ReadByteSeq(guids[i][0]); + recvData.ReadByteSeq(guids[i][3]); + + recvData >> position; + + recvData.ReadByteSeq(guids[i][2]); + recvData.ReadByteSeq(guids[i][7]); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_LIST_SLOT); + stmt->setUInt8(0, position); + stmt->setUInt32(1, GUID_LOPART(guids[i])); + trans->Append(stmt); + } + + CharacterDatabase.CommitTransaction(trans); +} + +void WorldSession::HandleOpeningCinematic(WorldPacket& /*recvData*/) +{ + // Only players that has not yet gained any experience can use this + if (_player->GetUInt32Value(PLAYER_XP)) + return; + + if (ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(_player->getClass())) + { + if (classEntry->CinematicSequence) + _player->SendCinematicStart(classEntry->CinematicSequence); + else if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(_player->getRace())) + _player->SendCinematicStart(raceEntry->CinematicSequence); + } +} |