aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp192
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp83
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h49
-rw-r--r--src/server/game/Server/Packet.cpp2
-rw-r--r--src/server/game/Server/Packet.h6
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.h5
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.cpp196
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.h116
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__