diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 192 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 2 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 83 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 49 | ||||
-rw-r--r-- | src/server/game/Server/Packet.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/Packet.h | 6 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuthenticationPackets.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuthenticationPackets.h | 5 | ||||
-rw-r--r-- | src/server/game/Server/Packets/CharacterPackets.cpp | 196 | ||||
-rw-r--r-- | src/server/game/Server/Packets/CharacterPackets.h | 116 |
10 files changed, 396 insertions, 257 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e38300a1c2d..a27a9008d63 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -85,51 +85,6 @@ #define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS) -enum CharacterFlags -{ - CHARACTER_FLAG_NONE = 0x00000000, - CHARACTER_FLAG_UNK1 = 0x00000001, - CHARACTER_FLAG_UNK2 = 0x00000002, - CHARACTER_LOCKED_FOR_TRANSFER = 0x00000004, - CHARACTER_FLAG_UNK4 = 0x00000008, - CHARACTER_FLAG_UNK5 = 0x00000010, - CHARACTER_FLAG_UNK6 = 0x00000020, - CHARACTER_FLAG_UNK7 = 0x00000040, - CHARACTER_FLAG_UNK8 = 0x00000080, - CHARACTER_FLAG_UNK9 = 0x00000100, - CHARACTER_FLAG_UNK10 = 0x00000200, - CHARACTER_FLAG_HIDE_HELM = 0x00000400, - CHARACTER_FLAG_HIDE_CLOAK = 0x00000800, - CHARACTER_FLAG_UNK13 = 0x00001000, - CHARACTER_FLAG_GHOST = 0x00002000, - CHARACTER_FLAG_RENAME = 0x00004000, - CHARACTER_FLAG_UNK16 = 0x00008000, - CHARACTER_FLAG_UNK17 = 0x00010000, - CHARACTER_FLAG_UNK18 = 0x00020000, - CHARACTER_FLAG_UNK19 = 0x00040000, - CHARACTER_FLAG_UNK20 = 0x00080000, - CHARACTER_FLAG_UNK21 = 0x00100000, - CHARACTER_FLAG_UNK22 = 0x00200000, - CHARACTER_FLAG_UNK23 = 0x00400000, - CHARACTER_FLAG_UNK24 = 0x00800000, - CHARACTER_FLAG_LOCKED_BY_BILLING = 0x01000000, - CHARACTER_FLAG_DECLINED = 0x02000000, - CHARACTER_FLAG_UNK27 = 0x04000000, - CHARACTER_FLAG_UNK28 = 0x08000000, - CHARACTER_FLAG_UNK29 = 0x10000000, - CHARACTER_FLAG_UNK30 = 0x20000000, - CHARACTER_FLAG_UNK31 = 0x40000000, - CHARACTER_FLAG_UNK32 = 0x80000000 -}; - -enum CharacterCustomizeFlags -{ - CHAR_CUSTOMIZE_FLAG_NONE = 0x00000000, - CHAR_CUSTOMIZE_FLAG_CUSTOMIZE = 0x00000001, // name, gender, etc... - CHAR_CUSTOMIZE_FLAG_FACTION = 0x00010000, // name, gender, faction, etc... - CHAR_CUSTOMIZE_FLAG_RACE = 0x00100000 // name, gender, race, etc... -}; - // corpse reclaim times #define DEATH_EXPIRE_STEP (5*MINUTE) #define MAX_DEATH_COUNT 3 @@ -1953,153 +1908,6 @@ void Player::InnEnter(time_t time, uint32 mapid, float x, float y, float z) time_inn_enter = time; } -bool Player::BuildEnumData(PreparedQueryResult result, ByteBuffer* dataBuffer) -{ - // 0 1 2 3 4 5 6 7 - // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " - // 8 9 10 11 12 13 14 - // "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 20 21 22 - // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_banned.guid, characters.slot, character_declinedname.genitive" - - Field* fields = result->Fetch(); - - ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); - std::string name = fields[1].GetString(); - uint8 playerRace = fields[2].GetUInt8(); - uint8 playerClass = fields[3].GetUInt8(); - uint8 gender = fields[4].GetUInt8(); - uint8 skin = uint8(fields[5].GetUInt32() & 0xFF); - uint8 face = uint8((fields[5].GetUInt32() >> 8) & 0xFF); - uint8 hairStyle = uint8((fields[5].GetUInt32() >> 16) & 0xFF); - uint8 hairColor = uint8((fields[5].GetUInt32() >> 24) & 0xFF); - uint8 facialHair = uint8(fields[6].GetUInt32() & 0xFF); - uint8 level = fields[7].GetUInt8(); - uint32 zone = fields[8].GetUInt16(); - uint32 mapId = uint32(fields[9].GetUInt16()); - float x = fields[10].GetFloat(); - float y = fields[11].GetFloat(); - float z = fields[12].GetFloat(); - uint64 guildId = fields[13].GetUInt64(); - ObjectGuid guildGuid; - if (guildId) - guildGuid = ObjectGuid::Create<HighGuid::Guild>(guildId); - uint32 playerFlags = fields[14].GetUInt32(); - uint32 atLoginFlags = fields[15].GetUInt16(); - Tokenizer equipment(fields[19].GetString(), ' '); - uint8 slot = fields[21].GetUInt8(); - - uint32 charFlags = 0; - if (playerFlags & PLAYER_FLAGS_HIDE_HELM) - charFlags |= CHARACTER_FLAG_HIDE_HELM; - - if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK) - charFlags |= CHARACTER_FLAG_HIDE_CLOAK; - - if (playerFlags & PLAYER_FLAGS_GHOST) - charFlags |= CHARACTER_FLAG_GHOST; - - if (atLoginFlags & AT_LOGIN_RENAME) - charFlags |= CHARACTER_FLAG_RENAME; - - if (fields[20].GetUInt32()) - charFlags |= CHARACTER_FLAG_LOCKED_BY_BILLING; - - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[22].GetString().empty()) - charFlags |= CHARACTER_FLAG_DECLINED; - - uint32 customizationFlag = 0; - if (atLoginFlags & AT_LOGIN_CUSTOMIZE) - customizationFlag = CHAR_CUSTOMIZE_FLAG_CUSTOMIZE; - else if (atLoginFlags & AT_LOGIN_CHANGE_FACTION) - customizationFlag = CHAR_CUSTOMIZE_FLAG_FACTION; - else if (atLoginFlags & AT_LOGIN_CHANGE_RACE) - customizationFlag = CHAR_CUSTOMIZE_FLAG_RACE; - - uint32 petDisplayId = 0; - uint32 petLevel = 0; - uint32 petFamily = 0; - // show pet at selection character in character list only for non-ghost character - if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (playerClass == CLASS_WARLOCK || playerClass == CLASS_HUNTER || playerClass == CLASS_DEATH_KNIGHT)) - { - uint32 entry = fields[16].GetUInt32(); - CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(entry); - if (creatureInfo) - { - petDisplayId = fields[17].GetUInt32(); - petLevel = fields[18].GetUInt16(); - petFamily = creatureInfo->family; - } - } - - // Packet content flags - *dataBuffer << guid; - *dataBuffer << uint8(slot); // List order - *dataBuffer << uint8(playerRace); // Race - *dataBuffer << uint8(playerClass); // Class - *dataBuffer << uint8(gender); // Gender - *dataBuffer << uint8(skin); // Skin - *dataBuffer << uint8(face); // Face - *dataBuffer << uint8(hairStyle); // Hair style - *dataBuffer << uint8(hairColor); // Hair color - *dataBuffer << uint8(facialHair); // Facial hair - *dataBuffer << uint8(level); // Level - *dataBuffer << uint32(zone); // Zone ids - *dataBuffer << uint32(mapId); // Map Id - *dataBuffer << float(y); // Y - *dataBuffer << float(x); // X - *dataBuffer << float(z); // Z - *dataBuffer << guildGuid; - *dataBuffer << uint32(charFlags); // Character flag - *dataBuffer << uint32(customizationFlag); // Character customization flags - *dataBuffer << uint32(0); // Character flags 3 - *dataBuffer << uint32(petDisplayId); // Pet DisplayID - *dataBuffer << uint32(petLevel); // Pet level - *dataBuffer << uint32(petFamily); // Pet family - - for (int i = 0; i < 2; i++) // ProfessionIDs - *dataBuffer << uint32(0); - - // Character data - for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot) - { - uint32 visualbase = slot * 2; - uint32 itemId = GetUInt32ValueFromArray(equipment, visualbase); - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); - if (!proto) - { - *dataBuffer << uint32(0); - *dataBuffer << uint32(0); - *dataBuffer << uint8(0); - continue; - } - - SpellItemEnchantmentEntry const* enchant = NULL; - uint32 enchants = GetUInt32ValueFromArray(equipment, visualbase + 1); - for (uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) - { - // values stored in 2 uint16 - uint32 enchantId = 0x0000FFFF & (enchants >> enchantSlot*16); - if (!enchantId) - continue; - - enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId); - if (enchant) - break; - } - - *dataBuffer << uint32(proto->DisplayInfoID); - *dataBuffer << uint32(enchant ? enchant->aura_id : 0); - *dataBuffer << uint8(proto->InventoryType); - } - - dataBuffer->WriteBits(uint32(name.length()), 6); - dataBuffer->WriteBit(atLoginFlags & AT_LOGIN_FIRST); - dataBuffer->WriteBit(0); // BoostInProgress - dataBuffer->WriteString(name); // Name - return true; -} - void Player::ToggleAFK() { ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 41291dabb68..74222bd162f 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1293,8 +1293,6 @@ class Player : public Unit, public GridObject<Player> void Update(uint32 time) override; - static bool BuildEnumData(PreparedQueryResult result, ByteBuffer* dataBuffer); - void SetInWater(bool apply); bool IsInWater() const override { return m_isInWater; } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 58e431ac2bd..a3ed092e56a 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -21,6 +21,7 @@ #include "ArenaTeamMgr.h" #include "Battleground.h" #include "CalendarMgr.h" +#include "CharacterPackets.h" #include "Chat.h" #include "Common.h" #include "DatabaseEnv.h" @@ -222,45 +223,35 @@ bool LoginQueryHolder::Initialize() void WorldSession::HandleCharEnum(PreparedQueryResult result) { - uint32 charCount = 0; - WorldPacket data(SMSG_CHAR_ENUM); - data.WriteBit(1); // Success - data.WriteBit(0); // IsDeleted (used for character undelete list) - + WorldPackets::Character::CharEnumResult charEnum; + charEnum.Success = true; + charEnum.IsDeletedCharacters = false; if (result) { _legitCharacters.clear(); - charCount = uint32(result->GetRowCount()); - data << uint32(charCount); - data << uint32(0); // FactionChangeRestrictions - - data.reserve(charCount * 450); // Guessed - do { - ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>((*result)[0].GetUInt64()); + Field* fields = result->Fetch(); + WorldPackets::Character::CharEnumResult::CharacterInfo charInfo(fields); - TC_LOG_INFO("network", "Loading char guid %s from account %u.", guid.ToString().c_str(), GetAccountId()); + TC_LOG_INFO("network", "Loading char guid %s from account %u.", charInfo.Guid.ToString().c_str(), GetAccountId()); - Player::BuildEnumData(result, &data); + // Do not allow locked characters to login + if (!(charInfo.Flags & (CHARACTER_FLAG_LOCKED_FOR_TRANSFER | CHARACTER_FLAG_LOCKED_BY_BILLING))) + _legitCharacters.insert(charInfo.Guid); - // Do not allow banned characters to log in - if (!(*result)[20].GetUInt64()) - _legitCharacters.insert(guid); + if (!sWorld->HasCharacterNameData(charInfo.Guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. + sWorld->AddCharacterNameData(charInfo.Guid, charInfo.Name, charInfo.Sex, charInfo.Race, charInfo.Class, charInfo.Level); - if (!sWorld->HasCharacterNameData(guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. - sWorld->AddCharacterNameData(guid, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8()); - } while (result->NextRow()); - } - else - { - data << uint32(0); // CharCount - data << uint32(0); // FactionChangeRestrictions + charEnum.Characters.emplace_back(charInfo); + } + while (result->NextRow()); } - SendPacket(&data); + charEnum.Write(); + SendPacket(&charEnum.GetWorldPacket()); } void WorldSession::HandleCharEnumOpcode(WorldPacket& /*recvData*/) @@ -763,38 +754,23 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData) return; } + TC_LOG_DEBUG("network", "WORLD: Recvd Player Logon Message"); + m_playerLoading = true; - ObjectGuid playerGuid; - TC_LOG_DEBUG("network", "WORLD: Recvd Player Logon Message"); - 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]); - - TC_LOG_DEBUG("network", "Character %s logging in", playerGuid.ToString().c_str()); - - if (!IsLegitCharacterForAccount(playerGuid)) - { - TC_LOG_ERROR("network", "Account (%u) can't login with that character (%s).", GetAccountId(), playerGuid.ToString().c_str()); + WorldPackets::Character::PlayerLogin playerLogin(std::move(recvData)); + playerLogin.Read(); + + TC_LOG_DEBUG("network", "Character %s logging in", playerLogin.Guid.ToString().c_str()); + + if (!IsLegitCharacterForAccount(playerLogin.Guid)) + { + TC_LOG_ERROR("network", "Account (%u) can't login with that character (%s).", GetAccountId(), playerLogin.Guid.ToString().c_str()); KickPlayer(); return; } - LoginQueryHolder *holder = new LoginQueryHolder(GetAccountId(), playerGuid); + LoginQueryHolder* holder = new LoginQueryHolder(GetAccountId(), playerLogin.Guid); if (!holder->Initialize()) { delete holder; // delete all unprocessed queries @@ -1083,9 +1059,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) if (pCurrChar->IsGameMaster()) SendNotification(LANG_GM_ON); - std::string IP_str = GetRemoteAddress(); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Login Character: [%s] (%s) Level: %d", - GetAccountId(), IP_str.c_str(), pCurrChar->GetName().c_str(), pCurrChar->GetGUID().ToString().c_str(), pCurrChar->getLevel()); + GetAccountId(), GetRemoteAddress().c_str(), pCurrChar->GetName().c_str(), pCurrChar->GetGUID().ToString().c_str(), pCurrChar->getLevel()); if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED)) pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 6c8df497a1a..097ac61ec8a 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -292,7 +292,7 @@ enum ItemQualities ITEM_QUALITY_EPIC = 4, // PURPLE ITEM_QUALITY_LEGENDARY = 5, // ORANGE ITEM_QUALITY_ARTIFACT = 6, // LIGHT YELLOW - ITEM_QUALITY_HEIRLOOM = 7 + ITEM_QUALITY_HEIRLOOM = 7 }; #define MAX_ITEM_QUALITY 8 @@ -853,6 +853,51 @@ enum SheathTypes #define MAX_SHEATHETYPE 8 +enum CharacterFlags +{ + CHARACTER_FLAG_NONE = 0x00000000, + CHARACTER_FLAG_UNK1 = 0x00000001, + CHARACTER_FLAG_UNK2 = 0x00000002, + CHARACTER_FLAG_LOCKED_FOR_TRANSFER = 0x00000004, + CHARACTER_FLAG_UNK4 = 0x00000008, + CHARACTER_FLAG_UNK5 = 0x00000010, + CHARACTER_FLAG_UNK6 = 0x00000020, + CHARACTER_FLAG_UNK7 = 0x00000040, + CHARACTER_FLAG_UNK8 = 0x00000080, + CHARACTER_FLAG_UNK9 = 0x00000100, + CHARACTER_FLAG_UNK10 = 0x00000200, + CHARACTER_FLAG_HIDE_HELM = 0x00000400, + CHARACTER_FLAG_HIDE_CLOAK = 0x00000800, + CHARACTER_FLAG_UNK13 = 0x00001000, + CHARACTER_FLAG_GHOST = 0x00002000, + CHARACTER_FLAG_RENAME = 0x00004000, + CHARACTER_FLAG_UNK16 = 0x00008000, + CHARACTER_FLAG_UNK17 = 0x00010000, + CHARACTER_FLAG_UNK18 = 0x00020000, + CHARACTER_FLAG_UNK19 = 0x00040000, + CHARACTER_FLAG_UNK20 = 0x00080000, + CHARACTER_FLAG_UNK21 = 0x00100000, + CHARACTER_FLAG_UNK22 = 0x00200000, + CHARACTER_FLAG_UNK23 = 0x00400000, + CHARACTER_FLAG_UNK24 = 0x00800000, + CHARACTER_FLAG_LOCKED_BY_BILLING = 0x01000000, + CHARACTER_FLAG_DECLINED = 0x02000000, + CHARACTER_FLAG_UNK27 = 0x04000000, + CHARACTER_FLAG_UNK28 = 0x08000000, + CHARACTER_FLAG_UNK29 = 0x10000000, + CHARACTER_FLAG_UNK30 = 0x20000000, + CHARACTER_FLAG_UNK31 = 0x40000000, + CHARACTER_FLAG_UNK32 = 0x80000000 +}; + +enum CharacterCustomizeFlags +{ + CHAR_CUSTOMIZE_FLAG_NONE = 0x00000000, + CHAR_CUSTOMIZE_FLAG_CUSTOMIZE = 0x00000001, // name, gender, etc... + CHAR_CUSTOMIZE_FLAG_FACTION = 0x00010000, // name, gender, faction, etc... + CHAR_CUSTOMIZE_FLAG_RACE = 0x00100000 // name, gender, race, etc... +}; + enum CharacterSlot { SLOT_HEAD = 0, @@ -3669,7 +3714,7 @@ inline uint8 ClassByQuestSort(int32 QuestSort) enum SkillType { SKILL_NONE = 0, - + SKILL_FROST = 6, SKILL_FIRE = 8, SKILL_ARMS = 26, diff --git a/src/server/game/Server/Packet.cpp b/src/server/game/Server/Packet.cpp index bff5643f410..10b472bee67 100644 --- a/src/server/game/Server/Packet.cpp +++ b/src/server/game/Server/Packet.cpp @@ -17,6 +17,6 @@ #include "Packet.h" -WorldPackets::ServerPacket::ServerPacket(OpcodeServer opcode, size_t initialSize = 200) : Packet(WorldPacket(opcode, initialSize)) +WorldPackets::ServerPacket::ServerPacket(OpcodeServer opcode, size_t initialSize /*= 200*/) : Packet(WorldPacket(opcode, initialSize)) { } diff --git a/src/server/game/Server/Packet.h b/src/server/game/Server/Packet.h index bda0166098d..e7baf830944 100644 --- a/src/server/game/Server/Packet.h +++ b/src/server/game/Server/Packet.h @@ -33,6 +33,7 @@ namespace WorldPackets virtual void Read() = 0; WorldPacket& GetWorldPacket() { return _worldPacket; } + size_t GetSize() const { return _worldPacket.size(); } protected: WorldPacket _worldPacket; @@ -41,11 +42,10 @@ namespace WorldPackets class ServerPacket : public Packet { public: - ServerPacket(OpcodeServer opcode, size_t initialSize); + ServerPacket(OpcodeServer opcode, size_t initialSize = 200); void Read() override final { ASSERT(!"Read not implemented for server packets."); } - size_t GetSize() const { return _worldPacket.size(); } void Reset() { _worldPacket.clear(); } }; @@ -58,4 +58,4 @@ namespace WorldPackets }; } -#endif +#endif // PacketBaseWorld_h__ diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index c64ef37d320..ae3c13b64f5 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -49,7 +49,7 @@ void WorldPackets::Auth::AuthSession::Read() } WorldPackets::Auth::AuthResponse::AuthResponse() - : ServerPacket(SMSG_AUTH_RESPONSE, 132) + : ServerPacket(SMSG_AUTH_RESPONSE, 132) { WaitInfo.HasValue = false; SuccessInfo.HasValue = false; diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h index 41b3d7cb257..305a841d4e7 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.h +++ b/src/server/game/Server/Packets/AuthenticationPackets.h @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef AuthenticationPackets_h__ +#ifndef AuthenticationPacketsWorld_h__ +#define AuthenticationPacketsWorld_h__ #include "Packet.h" #include "Util.h" @@ -134,4 +135,4 @@ namespace WorldPackets } } -#endif +#endif // AuthenticationPacketsWorld_h__ diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp new file mode 100644 index 00000000000..ff44777ac79 --- /dev/null +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CharacterPackets.h" + +WorldPackets::Character::CharEnumResult::CharacterInfo::CharacterInfo(Field* fields) +{ + // 0 1 2 3 4 5 6 7 + // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " + // 8 9 10 11 12 13 14 + // "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " + // 15 16 17 18 19 20 21 22 + // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_banned.guid, characters.slot, character_declinedname.genitive" + + Guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); + Name = fields[1].GetString(); + Race = fields[2].GetUInt8(); + Class = fields[3].GetUInt8(); + Sex = fields[4].GetUInt8(); + Skin = uint8(fields[5].GetUInt32() & 0xFF); + Face = uint8((fields[5].GetUInt32() >> 8) & 0xFF); + HairStyle = uint8((fields[5].GetUInt32() >> 16) & 0xFF); + HairColor = uint8((fields[5].GetUInt32() >> 24) & 0xFF); + FacialHair = uint8(fields[6].GetUInt32() & 0xFF); + Level = fields[7].GetUInt8(); + ZoneId = fields[8].GetUInt16(); + MapId = fields[9].GetUInt16(); + PreLoadPosition.x = fields[10].GetFloat(); + PreLoadPosition.y = fields[11].GetFloat(); + PreLoadPosition.z = fields[12].GetFloat(); + + if (uint32 guildId = fields[13].GetUInt32()) + GuildGuid = ObjectGuid::Create<HighGuid::Guild>(guildId); + + uint32 playerFlags = fields[14].GetUInt32(); + uint32 atLoginFlags = fields[15].GetUInt16(); + + if (playerFlags & PLAYER_FLAGS_HIDE_HELM) + Flags |= CHARACTER_FLAG_HIDE_HELM; + + if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK) + Flags |= CHARACTER_FLAG_HIDE_CLOAK; + + if (playerFlags & PLAYER_FLAGS_GHOST) + Flags |= CHARACTER_FLAG_GHOST; + + if (atLoginFlags & AT_LOGIN_RENAME) + Flags |= CHARACTER_FLAG_RENAME; + + if (fields[20].GetUInt32()) + Flags |= CHARACTER_FLAG_LOCKED_BY_BILLING; + + if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[22].GetString().empty()) + Flags |= CHARACTER_FLAG_DECLINED; + + if (atLoginFlags & AT_LOGIN_CUSTOMIZE) + CustomizationFlag = CHAR_CUSTOMIZE_FLAG_CUSTOMIZE; + else if (atLoginFlags & AT_LOGIN_CHANGE_FACTION) + CustomizationFlag = CHAR_CUSTOMIZE_FLAG_FACTION; + else if (atLoginFlags & AT_LOGIN_CHANGE_RACE) + CustomizationFlag = CHAR_CUSTOMIZE_FLAG_RACE; + + Flags3 = 0; + FirstLogin = (atLoginFlags & AT_LOGIN_FIRST) != 0; + + // show pet at selection character in character list only for non-ghost character + if (!(playerFlags & PLAYER_FLAGS_GHOST) && (Class == CLASS_WARLOCK || Class == CLASS_HUNTER || Class == CLASS_DEATH_KNIGHT)) + { + if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(fields[16].GetUInt32())) + { + Pet.CreatureDisplayId = fields[17].GetUInt32(); + Pet.Level = fields[18].GetUInt16(); + Pet.CreatureFamily = creatureInfo->family; + } + } + + BoostInProgress = false; + ProfessionIds[0] = 0; + ProfessionIds[1] = 0; + + Tokenizer equipment(fields[19].GetString(), ' '); + ListPosition = fields[21].GetUInt8(); + + for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot) + { + uint32 visualBase = slot * 2; + uint32 itemId = Player::GetUInt32ValueFromArray(equipment, visualBase); + if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId)) + { + uint32 enchants = Player::GetUInt32ValueFromArray(equipment, visualBase + 1); + for (uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) + { + // values stored in 2 uint16 + uint32 enchantId = 0x0000FFFF & (enchants >> enchantSlot * 16); + if (!enchantId) + continue; + + if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId)) + { + VisualItems[slot].DisplayEnchantId = enchant->aura_id; + break; + } + } + + VisualItems[slot].DisplayId = proto->DisplayInfoID; + VisualItems[slot].InventoryType = uint8(proto->InventoryType); + } + } +} + +WorldPackets::Character::CharEnumResult::CharEnumResult() + : ServerPacket(SMSG_CHAR_ENUM) { } + +void WorldPackets::Character::CharEnumResult::Write() +{ + _worldPacket.reserve(9 + Characters.size() * sizeof(CharacterInfo) + FactionChangeRestrictions.size() * sizeof(RestrictedFactionChangeRuleInfo)); + + _worldPacket.WriteBit(Success); + _worldPacket.WriteBit(IsDeletedCharacters); + _worldPacket << uint32(Characters.size()); + _worldPacket << uint32(FactionChangeRestrictions.size()); + + for (CharacterInfo const& charInfo : Characters) + { + _worldPacket << charInfo.Guid; + _worldPacket << uint8(charInfo.ListPosition); + _worldPacket << uint8(charInfo.Race); + _worldPacket << uint8(charInfo.Class); + _worldPacket << uint8(charInfo.Sex); + _worldPacket << uint8(charInfo.Skin); + _worldPacket << uint8(charInfo.Face); + _worldPacket << uint8(charInfo.HairStyle); + _worldPacket << uint8(charInfo.HairColor); + _worldPacket << uint8(charInfo.FacialHair); + _worldPacket << uint8(charInfo.Level); + _worldPacket << uint32(charInfo.ZoneId); + _worldPacket << uint32(charInfo.MapId); + _worldPacket << float(charInfo.PreLoadPosition.x); + _worldPacket << float(charInfo.PreLoadPosition.y); + _worldPacket << float(charInfo.PreLoadPosition.z); + _worldPacket << charInfo.GuildGuid; + _worldPacket << uint32(charInfo.Flags); + _worldPacket << uint32(charInfo.CustomizationFlag); + _worldPacket << uint32(charInfo.Flags3); + _worldPacket << uint32(charInfo.Pet.CreatureDisplayId); + _worldPacket << uint32(charInfo.Pet.Level); + _worldPacket << uint32(charInfo.Pet.CreatureFamily); + + _worldPacket << uint32(charInfo.ProfessionIds[0]); + _worldPacket << uint32(charInfo.ProfessionIds[1]); + + for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot) + { + _worldPacket << uint32(charInfo.VisualItems[slot].DisplayId); + _worldPacket << uint32(charInfo.VisualItems[slot].DisplayEnchantId); + _worldPacket << uint8(charInfo.VisualItems[slot].InventoryType); + } + + _worldPacket.WriteBits(charInfo.Name.length(), 6); + _worldPacket.WriteBit(charInfo.FirstLogin); + _worldPacket.WriteBit(charInfo.BoostInProgress); + _worldPacket.WriteString(charInfo.Name); + } + + for (RestrictedFactionChangeRuleInfo const& rule : FactionChangeRestrictions) + { + _worldPacket << uint32(rule.Mask); + _worldPacket << uint8(rule.Race); + } +} + +WorldPackets::Character::PlayerLogin::PlayerLogin(WorldPacket&& packet) + : ClientPacket(std::move(packet)) +{ + ASSERT(_worldPacket.GetOpcode() == CMSG_PLAYER_LOGIN); +} + +void WorldPackets::Character::PlayerLogin::Read() +{ + _worldPacket >> Guid; + _worldPacket >> FarClip; +} diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h new file mode 100644 index 00000000000..2f8b069164a --- /dev/null +++ b/src/server/game/Server/Packets/CharacterPackets.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef CharacterPackets_h__ +#define CharacterPackets_h__ + +#include "Packet.h" +#include "Player.h" + +namespace WorldPackets +{ + namespace Character + { + class CharEnumResult final : public ServerPacket + { + public: + struct CharacterInfo + { + /** + * @fn void WorldPackets::Character::CharEnumResult::CharacterInfo::CharacterInfo(Field* fields); + * + * @brief Initialize the struct with values from QueryResult + * + * @param fields Field set of CharacterDatabaseStatements::CHAR_SEL_ENUM + */ + CharacterInfo(Field* fields); + + ObjectGuid Guid; + std::string Name; + uint8 ListPosition = 0; ///< Order of the characters in list + uint8 Race = 0; + uint8 Class = 0; + uint8 Sex = 0; + uint8 Skin = 0; + uint8 Face = 0; + uint8 HairStyle = 0; + uint8 HairColor = 0; + uint8 FacialHair = 0; + uint8 Level = 0; + uint32 ZoneId = 0; + uint32 MapId = 0; + G3D::Vector3 PreLoadPosition; + ObjectGuid GuildGuid; + uint32 Flags = 0; ///< Character flag @see enum CharacterFlags + uint32 CustomizationFlag = 0; ///< Character customization flags @see enum CharacterCustomizeFlags + uint32 Flags3 = 0; ///< Character flags 3 @todo research + bool FirstLogin = false; + + struct PetInfo + { + uint32 CreatureDisplayId = 0; ///< PetCreatureDisplayID + uint32 Level = 0; ///< PetExperienceLevel + uint32 CreatureFamily = 0; ///< PetCreatureFamilyID + } Pet; + + bool BoostInProgress = false; ///< @todo + uint32 ProfessionIds[2]; ///< @todo + + struct VisualItemInfo + { + uint32 DisplayId = 0; + uint32 DisplayEnchantId = 0; + uint8 InventoryType = 0; + }; + + VisualItemInfo VisualItems[INVENTORY_SLOT_BAG_END]; + }; + + struct RestrictedFactionChangeRuleInfo + { + RestrictedFactionChangeRuleInfo(uint32 mask, uint8 race) + : Mask(mask), Race(race) { } + + uint32 Mask = 0; + uint8 Race = 0; + }; + + CharEnumResult(); + + void Write() override; + + bool Success = false; ///< + bool IsDeletedCharacters = false; ///< used for character undelete list + + std::list<CharacterInfo> Characters; ///< all characters on the list + std::list<RestrictedFactionChangeRuleInfo> FactionChangeRestrictions; ///< @todo: research + }; + + class PlayerLogin final : public ClientPacket + { + public: + PlayerLogin(WorldPacket&& packet); + + void Read() override; + + ObjectGuid Guid; ///< Guid of the player that is logging in + float FarClip = 0.0f; ///< Visibility distance (for terrain) + }; + } +} + +#endif // CharacterPackets_h__ |