diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 15111101eb3..a30118e0400 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -664,6 +664,7 @@ Guild::Member::Member(ObjectGuid::LowType guildId, ObjectGuid guid, uint8 rankId m_zoneId(0), m_level(0), m_class(0), + _gender(0), m_flags(GUILDMEMBER_STATUS_NONE), m_logoutTime(::time(nullptr)), m_accountId(0), @@ -683,6 +684,7 @@ void Guild::Member::SetStats(Player* player) m_level = player->getLevel(); m_class = player->getClass(); m_zoneId = player->GetZoneId(); + _gender = player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER); m_accountId = player->GetSession()->GetAccountId(); m_achievementPoints = player->GetAchievementPoints(); m_totalReputation = player->GetReputation(PLAYER_GUILD_REPUTATION); @@ -797,6 +799,8 @@ bool Guild::Member::LoadFromDB(Field* fields) m_zoneId = Player::GetZoneIdFromDB(m_guid); } + + ResetFlags(); return true; } @@ -818,6 +822,13 @@ bool Guild::Member::CheckStats() const return true; } +float Guild::Member::GetInactiveDays() const +{ + if (IsOnline()) + return 0.0f; + return float(::time(nullptr) - GetLogoutTime()) / float(DAY); +} + Player* Guild::Member::FindPlayer() const { return ObjectAccessor::FindPlayer(m_guid); @@ -1523,87 +1534,54 @@ bool Guild::SetName(std::string const& name) void Guild::HandleRoster(WorldSession* session) { - ByteBuffer memberData(100); - // Guess size - WorldPacket data(SMSG_GUILD_ROSTER, 100); - data.WriteBits(m_motd.length(), 11); - data.WriteBits(m_members.size(), 18); + WorldPackets::Guild::GuildRoster roster; - for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) + roster.NumAccounts = int32(m_accountsNumber); + roster.CreateDate = uint32(m_createdDate); + roster.GuildFlags = 0; + roster.WeeklyRepCap = sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP); + roster.MemberData.reserve(m_members.size()); + + for (auto itr : m_members) { - Member* member = itr->second; - size_t pubNoteLength = member->GetPublicNote().length(); - size_t offNoteLength = member->GetOfficerNote().length(); + Member* member = itr.second; - ObjectGuid guid = member->GetGUID(); - data.WriteBit(guid[3]); - data.WriteBit(guid[4]); - data.WriteBit(0); // Has Authenticator - data.WriteBit(0); // Can Scroll of Ressurect - data.WriteBits(pubNoteLength, 8); - data.WriteBits(offNoteLength, 8); - data.WriteBit(guid[0]); - data.WriteBits(member->GetName().length(), 7); - data.WriteBit(guid[1]); - data.WriteBit(guid[2]); - data.WriteBit(guid[6]); - data.WriteBit(guid[5]); - data.WriteBit(guid[7]); + WorldPackets::Guild::GuildRosterMemberData memberData; - memberData << uint8(member->GetClass()); - memberData << uint32(member->GetTotalReputation()); - memberData.WriteByteSeq(guid[0]); - memberData << uint64(member->GetWeekActivity()); - memberData << uint32(member->GetRankId()); - memberData << uint32(member->GetAchievementPoints()); + memberData.Guid = member->GetGUID(); + memberData.RankID = int32(member->GetRankId()); + memberData.AreaID = int32(member->GetZoneId()); + memberData.PersonalAchievementPoints = int32(member->GetAchievementPoints()); + memberData.GuildReputation = int32(member->GetTotalReputation()); + memberData.LastSave = member->GetInactiveDays(); + memberData.GuildRepToCap = sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP) - member->GetWeekReputation(); - // for (2 professions) - memberData << uint32(0) << uint32(0) << uint32(0); - memberData << uint32(0) << uint32(0) << uint32(0); + //GuildRosterProfessionData - memberData.WriteByteSeq(guid[2]); - memberData << uint8(member->GetFlags()); - memberData << uint32(member->GetZoneId()); - memberData << uint64(member->GetTotalActivity()); - memberData.WriteByteSeq(guid[7]); - memberData << uint32(sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP) - member->GetWeekReputation()); + memberData.VirtualRealmAddress = 0; + memberData.Status = member->GetFlags(); + memberData.Level = member->GetLevel(); + memberData.ClassID = member->GetClass(); + memberData.Gender = member->GetGender(); - if (pubNoteLength) - memberData.WriteString(member->GetPublicNote()); + memberData.Authenticated = false; + memberData.SorEligible = false; - memberData.WriteByteSeq(guid[3]); - memberData << uint8(member->GetLevel()); - memberData << int32(0); // unk - memberData.WriteByteSeq(guid[5]); - memberData.WriteByteSeq(guid[4]); - memberData << uint8(0); // unk - memberData.WriteByteSeq(guid[1]); - memberData << float(member->IsOnline() ? 0.0f : float(::time(nullptr) - member->GetLogoutTime()) / DAY); + memberData.Name = member->GetName(); + memberData.Note = member->GetPublicNote(); + memberData.OfficerNote = member->GetOfficerNote(); - if (offNoteLength) - memberData.WriteString(member->GetOfficerNote()); + memberData.TotalXP = member->GetTotalActivity(); + memberData.WeeklyXP = member->GetWeekActivity(); - memberData.WriteByteSeq(guid[6]); - memberData.WriteString(member->GetName()); + roster.MemberData.push_back(memberData); } - size_t infoLength = m_info.length(); - data.WriteBits(infoLength, 12); - - data.FlushBits(); - data.append(memberData); - - if (infoLength) - data.WriteString(m_info); - - data.WriteString(m_motd); - data << uint32(m_accountsNumber); - data << uint32(sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP)); - data.AppendPackedTime(m_createdDate); - data << uint32(0); + roster.WelcomeText = m_motd; + roster.InfoText = m_info; TC_LOG_DEBUG("guild", "SMSG_GUILD_ROSTER [%s]", session->GetPlayerInfo().c_str()); - session->SendPacket(&data); + session->SendPacket(roster.Write()); } void Guild::HandleQuery(WorldSession* session) diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index 40fad8c2460..95a6e632ee8 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -367,9 +367,11 @@ private: uint32 GetAccountId() const { return m_accountId; } uint8 GetRankId() const { return m_rankId; } uint64 GetLogoutTime() const { return m_logoutTime; } + float GetInactiveDays() const; std::string GetPublicNote() const { return m_publicNote; } std::string GetOfficerNote() const { return m_officerNote; } uint8 GetClass() const { return m_class; } + uint8 GetGender() const { return _gender; } uint8 GetLevel() const { return m_level; } uint8 GetFlags() const { return m_flags; } uint32 GetZoneId() const { return m_zoneId; } @@ -408,6 +410,7 @@ private: uint32 m_zoneId; uint8 m_level; uint8 m_class; + uint8 _gender; uint8 m_flags; uint64 m_logoutTime; uint32 m_accountId; diff --git a/src/server/game/Server/Packets/GuildPackets.cpp b/src/server/game/Server/Packets/GuildPackets.cpp index 2e8083a05f4..43a9043b174 100644 --- a/src/server/game/Server/Packets/GuildPackets.cpp +++ b/src/server/game/Server/Packets/GuildPackets.cpp @@ -215,3 +215,85 @@ WorldPacket const* WorldPackets::Guild::GuildXP::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Guild::GuildRoster::Write() +{ + _worldPacket.WriteBits(WelcomeText.length(), 11); + _worldPacket.WriteBits(MemberData.size(), 18); + + for (GuildRosterMemberData const& member : MemberData) + { + _worldPacket.WriteBit(member.Guid[3]); + _worldPacket.WriteBit(member.Guid[4]); + _worldPacket.WriteBit(member.Authenticated); + _worldPacket.WriteBit(member.SorEligible); + _worldPacket.WriteBits(member.Note.length(), 8); + _worldPacket.WriteBits(member.OfficerNote.length(), 8); + _worldPacket.WriteBit(member.Guid[0]); + _worldPacket.WriteBits(member.Name.length(), 7); + _worldPacket.WriteBit(member.Guid[1]); + _worldPacket.WriteBit(member.Guid[2]); + _worldPacket.WriteBit(member.Guid[6]); + _worldPacket.WriteBit(member.Guid[5]); + _worldPacket.WriteBit(member.Guid[7]); + } + + _worldPacket.WriteBits(InfoText.length(), 12); + _worldPacket.FlushBits(); + + for (GuildRosterMemberData const& member : MemberData) + _worldPacket << member; + + _worldPacket.WriteString(InfoText); + _worldPacket.WriteString(WelcomeText); + _worldPacket << uint32(NumAccounts); + _worldPacket << uint32(WeeklyRepCap); + _worldPacket.AppendPackedTime(CreateDate); + _worldPacket << uint32(GuildFlags); + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Guild::GuildRosterProfessionData const& rosterProfessionData) +{ + data << uint32(rosterProfessionData.Rank); + data << uint32(rosterProfessionData.Step); + data << uint32(rosterProfessionData.DbID); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Guild::GuildRosterMemberData const& rosterMemberData) +{ + data << uint8(rosterMemberData.ClassID); + data << uint32(rosterMemberData.GuildReputation); + data.WriteByteSeq(rosterMemberData.Guid[0]); + data << uint64(rosterMemberData.WeeklyXP); + data << uint32(rosterMemberData.RankID); + data << uint32(rosterMemberData.PersonalAchievementPoints); + + for (uint8 i = 0; i < 2; i++) + data << rosterMemberData.Profession[i]; + + data.WriteByteSeq(rosterMemberData.Guid[2]); + data << uint8(rosterMemberData.Status); + data << uint32(rosterMemberData.AreaID); + data << uint64(rosterMemberData.TotalXP); + data.WriteByteSeq(rosterMemberData.Guid[7]); + data << uint32(rosterMemberData.GuildRepToCap); + data.WriteString(rosterMemberData.Note); + data.WriteByteSeq(rosterMemberData.Guid[3]); + data << uint8(rosterMemberData.Level); + data << int32(rosterMemberData.VirtualRealmAddress); // Todo: Validate + data.WriteByteSeq(rosterMemberData.Guid[5]); + data.WriteByteSeq(rosterMemberData.Guid[4]); + data << uint8(rosterMemberData.Gender); + data.WriteByteSeq(rosterMemberData.Guid[1]); + data << float(rosterMemberData.LastSave); + data.WriteString(rosterMemberData.OfficerNote); + data.WriteByteSeq(rosterMemberData.Guid[6]); + data.WriteString(rosterMemberData.Name); + + return data; +} + diff --git a/src/server/game/Server/Packets/GuildPackets.h b/src/server/game/Server/Packets/GuildPackets.h index a62e97c2a5d..dc3c5482883 100644 --- a/src/server/game/Server/Packets/GuildPackets.h +++ b/src/server/game/Server/Packets/GuildPackets.h @@ -261,7 +261,57 @@ namespace WorldPackets int64 GuildRemainingXP = 0; int64 GuildCurrentXP; }; + + struct GuildRosterProfessionData + { + int32 DbID = 0; + int32 Rank = 0; + int32 Step = 0; + }; + + struct GuildRosterMemberData + { + ObjectGuid Guid; + int64 WeeklyXP = 0; + int64 TotalXP = 0; + int32 RankID = 0; + int32 AreaID = 0; + int32 PersonalAchievementPoints = 0; + int32 GuildReputation = 0; + int32 GuildRepToCap = 0; + float LastSave = 0.0f; + std::string Name; + uint32 VirtualRealmAddress = 0; + std::string Note; + std::string OfficerNote; + uint8 Status = 0; + uint8 Level = 0; + uint8 ClassID = 0; + uint8 Gender = 0; + bool Authenticated = false; + bool SorEligible = false; + GuildRosterProfessionData Profession[2]; + }; + + class GuildRoster final : public ServerPacket + { + public: + GuildRoster() : ServerPacket(SMSG_GUILD_ROSTER, 4 + 4 + 4 + 4) { } + + WorldPacket const* Write() override; + + std::vector MemberData; + std::string WelcomeText; + std::string InfoText; + uint32 CreateDate = 0; + int32 NumAccounts = 0; + int32 GuildFlags = 0; + int32 WeeklyRepCap = 0; + }; } } +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Guild::GuildRosterProfessionData const& rosterProfessionData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Guild::GuildRosterMemberData const& rosterMemberData); + #endif // GuildPackets_h__