diff options
Diffstat (limited to 'src/server/game')
| -rwxr-xr-x | src/server/game/Entities/Object/ObjectDefines.h | 1 | ||||
| -rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 3 | ||||
| -rw-r--r-- | src/server/game/Guilds/Guild.cpp | 5 | ||||
| -rwxr-xr-x | src/server/game/Guilds/Guild.h | 2 | ||||
| -rw-r--r-- | src/server/game/Guilds/GuildFinderMgr.cpp | 333 | ||||
| -rw-r--r-- | src/server/game/Guilds/GuildFinderMgr.h | 274 | ||||
| -rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Handlers/GuildFinderHandler.cpp | 442 | ||||
| -rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 32 | ||||
| -rwxr-xr-x | src/server/game/Server/Protocol/Opcodes.h | 2 | ||||
| -rwxr-xr-x | src/server/game/Server/WorldSession.h | 11 | ||||
| -rw-r--r-- | src/server/game/Tools/PlayerDump.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 19 | ||||
| -rwxr-xr-x | src/server/game/World/World.h | 6 |
14 files changed, 1113 insertions, 27 deletions
diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h index b971943954e..46baee4a284 100755 --- a/src/server/game/Entities/Object/ObjectDefines.h +++ b/src/server/game/Entities/Object/ObjectDefines.h @@ -57,6 +57,7 @@ enum HighGuid #define IS_CRE_OR_VEH_GUID(Guid) (IS_CREATURE_GUID(Guid) || IS_VEHICLE_GUID(Guid)) #define IS_CRE_OR_VEH_OR_PET_GUID(Guid)(IS_CRE_OR_VEH_GUID(Guid) || IS_PET_GUID(Guid)) #define IS_PLAYER_GUID(Guid) (GUID_HIPART(Guid) == HIGHGUID_PLAYER && Guid != 0) +#define IS_GUILD_GUID(Guid) (GUID_HIPART(Guid) == HIGHGUID_GUILD && Guid != 0) #define IS_UNIT_GUID(Guid) (IS_CRE_OR_VEH_OR_PET_GUID(Guid) || IS_PLAYER_GUID(Guid)) // special case for empty guid need check #define IS_ITEM_GUID(Guid) (GUID_HIPART(Guid) == HIGHGUID_ITEM) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 7d1734ee204..7886c0354f5 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12780,6 +12780,9 @@ void Unit::SetLevel(uint8 lvl) // group update if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetGroup()) ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL); + + if (GetTypeId() == TYPEID_PLAYER) + sWorld->UpdateCharacterNameDataLevel(ToPlayer()->GetGUIDLow(), lvl); } void Unit::SetHealth(uint32 val) diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index e7121b0fa81..92191551858 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -19,6 +19,7 @@ #include "DatabaseEnv.h" #include "Guild.h" #include "GuildMgr.h" +#include "GuildFinderMgr.h" #include "ScriptMgr.h" #include "Chat.h" #include "Config.h" @@ -1190,6 +1191,9 @@ void Guild::Disband() trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); + + sGuildFinderMgr->DeleteGuild(m_id); + sGuildMgr->RemoveGuild(m_id); } @@ -1665,6 +1669,7 @@ void Guild::HandleAcceptMember(WorldSession* session) { _LogEvent(GUILD_EVENT_LOG_JOIN_GUILD, player->GetGUIDLow()); _BroadcastEvent(GE_JOINED, player->GetGUID(), player->GetName()); + sGuildFinderMgr->RemoveMembershipRequest(player->GetGUIDLow(), GUID_LOPART(this->GetGUID())); } } diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index f3e18d8998b..f644e5d3592 100755 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -787,6 +787,8 @@ public: void ResetDailyExperience(); GuildNewsLog& GetNewsLog() { return _newsLog; } + EmblemInfo const& GetEmblemInfo() const { return m_emblemInfo; } + protected: uint32 m_id; std::string m_name; diff --git a/src/server/game/Guilds/GuildFinderMgr.cpp b/src/server/game/Guilds/GuildFinderMgr.cpp new file mode 100644 index 00000000000..c81abeec47a --- /dev/null +++ b/src/server/game/Guilds/GuildFinderMgr.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2008-2012 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 "ObjectMgr.h" +#include "GuildFinderMgr.h" +#include "GuildMgr.h" +#include "World.h" + +GuildFinderMgr::GuildFinderMgr() +{ +} + +GuildFinderMgr::~GuildFinderMgr() +{ +} + +void GuildFinderMgr::LoadFromDB() +{ + LoadGuildSettings(); + LoadMembershipRequests(); +} + +void GuildFinderMgr::LoadGuildSettings() +{ + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading guild finder guild-related settings..."); + // 0 1 2 3 4 5 6 7 + QueryResult result = CharacterDatabase.Query("SELECT gfgs.guildId, gfgs.availability, gfgs.classRoles, gfgs.interests, gfgs.level, gfgs.listed, gfgs.comment, c.race " + "FROM guild_finder_guild_settings gfgs " + "LEFT JOIN guild_member gm ON gm.guildid=gfgs.guildId " + "LEFT JOIN characters c ON c.guid = gm.guid LIMIT 1"); + + if (!result) + { + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild finder guild-related settings. Table `guild_finder_guild_settings` is empty."); + return; + } + + uint32 count = 0; + uint32 oldMSTime = getMSTime(); + do + { + Field* fields = result->Fetch(); + uint32 guildId = fields[0].GetUInt32(); + uint8 availability = fields[1].GetUInt8(); + uint8 classRoles = fields[2].GetUInt8(); + uint8 interests = fields[3].GetUInt8(); + uint8 level = fields[4].GetUInt8(); + bool listed = (fields[5].GetUInt8() != 0); + std::string comment = fields[6].GetString(); + + TeamId guildTeam = TEAM_ALLIANCE; + if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(fields[7].GetUInt8())) + if (raceEntry->TeamID == 1) + guildTeam = TEAM_HORDE; + + LFGuildSettings settings(listed, guildTeam, guildId, classRoles, availability, interests, level, comment); + _guildSettings[guildId] = settings; + + ++count; + } while (result->NextRow()); + + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild finder guild-related settings in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); +} + +void GuildFinderMgr::LoadMembershipRequests() +{ + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading guild finder membership requests..."); + // 0 1 2 3 4 5 6 + QueryResult result = CharacterDatabase.Query("SELECT guildId, playerGuid, availability, classRole, interests, comment, submitTime " + "FROM guild_finder_applicant"); + + if (!result) + { + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild finder membership requests. Table `guild_finder_applicant` is empty."); + return; + } + + uint32 count = 0; + uint32 oldMSTime = getMSTime(); + do + { + Field* fields = result->Fetch(); + uint32 guildId = fields[0].GetUInt32(); + uint32 playerId = fields[1].GetUInt32(); + uint8 availability = fields[2].GetUInt8(); + uint8 classRoles = fields[3].GetUInt8(); + uint8 interests = fields[4].GetUInt8(); + std::string comment = fields[5].GetString(); + uint32 submitTime = fields[6].GetUInt32(); + + MembershipRequest request(playerId, guildId, availability, classRoles, interests, comment, time_t(submitTime)); + + _membershipRequests[guildId].push_back(request); + + ++count; + } while (result->NextRow()); + + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild finder membership requests in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); +} + +void GuildFinderMgr::AddMembershipRequest(uint32 guildGuid, MembershipRequest const& request) +{ + _membershipRequests[guildGuid].push_back(request); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GUILD_FINDER_APPLICANT); + stmt->setUInt32(0, request.GetGuildId()); + stmt->setUInt32(1, request.GetPlayerGUID()); + stmt->setUInt8(2, request.GetAvailability()); + stmt->setUInt8(3, request.GetClassRoles()); + stmt->setUInt8(4, request.GetInterests()); + stmt->setString(5, request.GetComment()); + stmt->setUInt32(6, request.GetSubmitTime()); + trans->Append(stmt); + CharacterDatabase.CommitTransaction(trans); + + // Notify the applicant his submittion has been added + if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(request.GetPlayerGUID(), 0, HIGHGUID_PLAYER))) + SendMembershipRequestListUpdate(*player); + + // Notify the guild master and officers the list changed + if (Guild* guild = sGuildMgr->GetGuildById(guildGuid)) + SendApplicantListUpdate(*guild); +} + +void GuildFinderMgr::RemoveAllMembershipRequestsFromPlayer(uint32 playerId) +{ + for (MembershipRequestStore::iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr) + { + std::vector<MembershipRequest>::iterator itr2 = itr->second.begin(); + for(; itr2 != itr->second.end(); ++itr2) + if (itr2->GetPlayerGUID() == playerId) + break; + + if (itr2 == itr->second.end()) + return; + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT); + stmt->setUInt32(0, itr2->GetGuildId()); + stmt->setUInt32(1, itr2->GetPlayerGUID()); + trans->Append(stmt); + + CharacterDatabase.CommitTransaction(trans); + itr->second.erase(itr2); + + // Notify the guild master and officers the list changed + if (Guild* guild = sGuildMgr->GetGuildById(itr->first)) + SendApplicantListUpdate(*guild); + } +} + +void GuildFinderMgr::RemoveMembershipRequest(uint32 playerId, uint32 guildId) +{ + std::vector<MembershipRequest>::iterator itr = _membershipRequests[guildId].begin(); + for(; itr != _membershipRequests[guildId].end(); ++itr) + if (itr->GetPlayerGUID() == playerId) + break; + + if (itr == _membershipRequests[guildId].end()) + return; + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT); + stmt->setUInt32(0, itr->GetGuildId()); + stmt->setUInt32(1, itr->GetPlayerGUID()); + trans->Append(stmt); + + CharacterDatabase.CommitTransaction(trans); + + _membershipRequests[guildId].erase(itr); + + // Notify the applicant his submittion has been removed + if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(playerId, 0, HIGHGUID_PLAYER))) + SendMembershipRequestListUpdate(*player); + + // Notify the guild master and officers the list changed + if (Guild* guild = sGuildMgr->GetGuildById(guildId)) + SendApplicantListUpdate(*guild); +} + +std::list<MembershipRequest> GuildFinderMgr::GetAllMembershipRequestsForPlayer(uint32 playerGuid) +{ + std::list<MembershipRequest> resultSet; + for (MembershipRequestStore::const_iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr) + { + std::vector<MembershipRequest> const& guildReqs = itr->second; + for (std::vector<MembershipRequest>::const_iterator itr2 = guildReqs.begin(); itr2 != guildReqs.end(); ++itr2) + { + if (itr2->GetPlayerGUID() == playerGuid) + { + resultSet.push_back(*itr2); + break; + } + } + } + return resultSet; +} + +uint8 GuildFinderMgr::CountRequestsFromPlayer(uint32 playerId) +{ + uint8 result = 0; + for (MembershipRequestStore::const_iterator itr = _membershipRequests.begin(); itr != _membershipRequests.end(); ++itr) + { + for (std::vector<MembershipRequest>::const_iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) + { + if (itr2->GetPlayerGUID() != playerId) + continue; + ++result; + break; + } + } + return result; +} + +LFGuildStore GuildFinderMgr::GetGuildsMatchingSetting(LFGuildPlayer& settings, TeamId faction) +{ + LFGuildStore resultSet; + for (LFGuildStore::const_iterator itr = _guildSettings.begin(); itr != _guildSettings.end(); ++itr) + { + LFGuildSettings const& guildSettings = itr->second; + + if (guildSettings.GetTeam() != faction) + continue; + + if (!(guildSettings.GetAvailability() & settings.GetAvailability())) + continue; + + if (!(guildSettings.GetClassRoles() & settings.GetClassRoles())) + continue; + + if (!(guildSettings.GetInterests() & settings.GetInterests())) + continue; + + if (!(guildSettings.GetLevel() & settings.GetLevel())) + continue; + + resultSet.insert(std::make_pair(itr->first, guildSettings)); + } + + return resultSet; +} + +bool GuildFinderMgr::HasRequest(uint32 playerId, uint32 guildId) +{ + for (std::vector<MembershipRequest>::const_iterator itr = _membershipRequests[guildId].begin(); itr != _membershipRequests[guildId].end(); ++itr) + if (itr->GetPlayerGUID() == playerId) + return true; + return false; +} + +void GuildFinderMgr::SetGuildSettings(uint32 guildGuid, LFGuildSettings const& settings) +{ + _guildSettings[guildGuid] = settings; + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GUILD_FINDER_GUILD_SETTINGS); + stmt->setUInt32(0, settings.GetGUID()); + stmt->setUInt8(1, settings.GetAvailability()); + stmt->setUInt8(2, settings.GetClassRoles()); + stmt->setUInt8(3, settings.GetInterests()); + stmt->setUInt8(4, settings.GetLevel()); + stmt->setUInt8(5, settings.IsListed()); + stmt->setString(6, settings.GetComment()); + trans->Append(stmt); + + CharacterDatabase.CommitTransaction(trans); +} + +void GuildFinderMgr::DeleteGuild(uint32 guildId) +{ + std::vector<MembershipRequest>::iterator itr = _membershipRequests[guildId].begin(); + while (itr != _membershipRequests[guildId].end()) + { + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + uint32 applicant = itr->GetPlayerGUID(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT); + stmt->setUInt32(0, itr->GetGuildId()); + stmt->setUInt32(1, applicant); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS); + stmt->setUInt32(0, itr->GetGuildId()); + trans->Append(stmt); + + CharacterDatabase.CommitTransaction(trans); + _membershipRequests[guildId].erase(itr); + + // Notify the applicant his submition has been removed + if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(applicant, 0, HIGHGUID_PLAYER))) + SendMembershipRequestListUpdate(*player); + } + + _membershipRequests.erase(guildId); + _guildSettings.erase(guildId); + + // Notify the guild master the list changed (even if he's not a GM any more, not sure if needed) + if (Guild* guild = sGuildMgr->GetGuildById(guildId)) + SendApplicantListUpdate(*guild); +} + +void GuildFinderMgr::SendApplicantListUpdate(Guild& guild) +{ + WorldPacket data(SMSG_LF_GUILD_APPLICANT_LIST_UPDATED, 0); + if (Player* player = ObjectAccessor::FindPlayer(guild.GetLeaderGUID())) + player->SendDirectMessage(&data); + guild.BroadcastPacketToRank(&data, GR_OFFICER); +} + +void GuildFinderMgr::SendMembershipRequestListUpdate(Player& player) +{ + WorldPacket data(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, 0); + player.SendDirectMessage(&data); +} diff --git a/src/server/game/Guilds/GuildFinderMgr.h b/src/server/game/Guilds/GuildFinderMgr.h new file mode 100644 index 00000000000..169b42740aa --- /dev/null +++ b/src/server/game/Guilds/GuildFinderMgr.h @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2008-2012 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 __TRINITY_GUILDFINDER_H +#define __TRINITY_GUILDFINDER_H + +#include <ace/Singleton.h> +#include "Common.h" +#include "World.h" +#include "GuildMgr.h" + +enum GuildFinderOptionsInterest +{ + INTEREST_QUESTING = 0x01, + INTEREST_DUNGEONS = 0x02, + INTEREST_RAIDS = 0x04, + INTEREST_PVP = 0x08, + INTEREST_ROLE_PLAYING = 0x10, + ALL_INTERESTS = INTEREST_QUESTING | INTEREST_DUNGEONS | INTEREST_RAIDS | INTEREST_PVP | INTEREST_ROLE_PLAYING +}; + +enum GuildFinderOptionsAvailability +{ + AVAILABILITY_WEEKDAYS = 0x1, + AVAILABILITY_WEEKENDS = 0x2, + ALL_WEEK = AVAILABILITY_WEEKDAYS | AVAILABILITY_WEEKENDS +}; + +enum GuildFinderOptionsRoles +{ + GUILDFINDER_ROLE_TANK = 0x1, + GUILDFINDER_ROLE_HEALER = 0x2, + GUILDFINDER_ROLE_DPS = 0x4, + GUILDFINDER_ALL_ROLES = GUILDFINDER_ROLE_TANK | GUILDFINDER_ROLE_HEALER | GUILDFINDER_ROLE_DPS +}; + +enum GuildFinderOptionsLevel +{ + ANY_FINDER_LEVEL = 0x1, + MAX_FINDER_LEVEL = 0x2, + ALL_GUILDFINDER_LEVELS = ANY_FINDER_LEVEL | MAX_FINDER_LEVEL +}; + +/// Holds all required informations about a membership request +struct MembershipRequest +{ + public: + MembershipRequest(MembershipRequest const& settings) : _comment(settings.GetComment()) + { + _availability = settings.GetAvailability(); + _classRoles = settings.GetClassRoles(); + _interests = settings.GetInterests(); + _guildId = settings.GetGuildId(); + _playerGUID = settings.GetPlayerGUID(); + _time = settings.GetSubmitTime(); + } + + MembershipRequest(uint32 playerGUID, uint32 guildId, uint32 availability, uint32 classRoles, uint32 interests, std::string& comment, time_t submitTime) : + _playerGUID(playerGUID), _guildId(guildId), _availability(availability), _classRoles(classRoles), + _interests(interests), _time(submitTime), _comment(comment) {} + + MembershipRequest() : _playerGUID(0), _guildId(0), _availability(0), _classRoles(0), + _interests(0), _time(time(NULL)) {} + + uint32 GetGuildId() const { return _guildId; } + uint32 GetPlayerGUID() const { return _playerGUID; } + uint8 GetAvailability() const { return _availability; } + uint8 GetClassRoles() const { return _classRoles; } + uint8 GetInterests() const { return _interests; } + uint8 GetClass() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_class; } + uint8 GetLevel() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_level; } + time_t GetSubmitTime() const { return _time; } + time_t GetExpiryTime() const { return time_t(_time + 30 * 24 * 3600); } // Adding 30 days + std::string const& GetComment() const { return _comment; } + std::string const& GetName() const { return sWorld->GetCharacterNameData(GetPlayerGUID())->m_name; } + private: + std::string _comment; + + uint32 _guildId; + uint32 _playerGUID; + + uint8 _availability; + uint8 _classRoles; + uint8 _interests; + + time_t _time; +}; + +/// Holds all informations about a player's finder settings. _NOT_ stored in database. +struct LFGuildPlayer +{ + public: + LFGuildPlayer() + { + _guid = 0; + _roles = 0; + _availability = 0; + _interests = 0; + _level = 0; + } + + LFGuildPlayer(uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level) + { + _guid = guid; + _roles = role; + _availability = availability; + _interests = interests; + _level = level; + } + + LFGuildPlayer(uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level, std::string& comment) : _comment(comment) + { + _guid = guid; + _roles = role; + _availability = availability; + _interests = interests; + _level = level; + } + + LFGuildPlayer(LFGuildPlayer const& settings) : _comment(settings.GetComment()) + { + _guid = settings.GetGUID(); + _roles = settings.GetClassRoles(); + _availability = settings.GetAvailability(); + _interests = settings.GetInterests(); + _level = settings.GetLevel(); + } + + uint32 GetGUID() const { return _guid; } + uint8 GetClassRoles() const { return _roles; } + uint8 GetAvailability() const { return _availability; } + uint8 GetInterests() const { return _interests; } + uint8 GetLevel() const { return _level; } + std::string const& GetComment() const { return _comment; } + + private: + std::string _comment; + uint32 _guid; + uint8 _roles; + uint8 _availability; + uint8 _interests; + uint8 _level; +}; + +/// Holds settings for a guild in the finder system. Saved to database. +struct LFGuildSettings : public LFGuildPlayer +{ + public: + LFGuildSettings() : LFGuildPlayer(), _listed(false), _team(TEAM_ALLIANCE) {} + + LFGuildSettings(bool listed, TeamId team) : LFGuildPlayer(), _listed(listed), _team(team) {} + + LFGuildSettings(bool listed, TeamId team, uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level) : _listed(listed), + LFGuildPlayer(guid, role, availability, interests, level), _team(team) {} + + LFGuildSettings(bool listed, TeamId team, uint32 guid, uint8 role, uint8 availability, uint8 interests, uint8 level, std::string& comment) : _listed(listed), + LFGuildPlayer(guid, role, availability, interests, level, comment), _team(team) {} + + LFGuildSettings(LFGuildSettings const& settings) : _listed(settings.IsListed()), _team(settings.GetTeam()), + LFGuildPlayer(settings) {} + + + bool IsListed() const { return _listed; } + void SetListed(bool state) { _listed = state; } + + TeamId GetTeam() const { return _team; } + private: + TeamId _team; + bool _listed; +}; + +typedef std::map<uint32 /* guildGuid */, LFGuildSettings> LFGuildStore; +typedef std::map<uint32 /* guildGuid */, std::vector<MembershipRequest> > MembershipRequestStore; + +class GuildFinderMgr +{ + friend class ACE_Singleton<GuildFinderMgr, ACE_Null_Mutex>; + + private: + GuildFinderMgr(); + ~GuildFinderMgr(); + + LFGuildStore _guildSettings; + + MembershipRequestStore _membershipRequests; + + void LoadGuildSettings(); + void LoadMembershipRequests(); + + public: + void LoadFromDB(); + + /** + * @brief Stores guild settings and begins an asynchronous database insert + * @param guildGuid The guild's database guid. + * @param LFGuildSettings The guild's settings storage. + */ + void SetGuildSettings(uint32 guildGuid, LFGuildSettings const& settings); + + /** + * @brief Returns settings for a guild. + * @param guildGuid The guild's database guid. + */ + LFGuildSettings GetGuildSettings(uint32 guildGuid) { return _guildSettings[guildGuid]; } + + /** + * @brief Files a membership request to a guild + * @param guildGuid The guild's database GUID. + * @param MembershipRequest An object storing all data related to the request. + */ + void AddMembershipRequest(uint32 guildGuid, MembershipRequest const& request); + + /** + * @brief Removes all membership request from a player. + * @param playerId The player's database guid whose application shall be deleted. + */ + void RemoveAllMembershipRequestsFromPlayer(uint32 playerId); + + /** + * @brief Removes a membership request to a guild. + * @param playerId The player's database guid whose application shall be deleted. + * @param guildId The guild's database guid + */ + void RemoveMembershipRequest(uint32 playerId, uint32 guildId); + + /// wipes everything related to a guild. Used when that guild is disbanded + void DeleteGuild(uint32 guildId); + + /** + * @brief Returns a set of membership requests for a guild + * @param guildGuid The guild's database guid. + */ + std::vector<MembershipRequest> GetAllMembershipRequestsForGuild(uint32 guildGuid) { return _membershipRequests[guildGuid]; } + + /** + * @brief Returns a list of membership requests for a player. + * @param playerGuid The player's database guid. + */ + std::list<MembershipRequest> GetAllMembershipRequestsForPlayer(uint32 playerGuid); + + /** + * @brief Returns a store of guilds matching the settings provided, using bitmask operators. + * @param settings The player's finder settings + * @param teamId The player's faction (TEAM_ALLIANCE or TEAM_HORDE) + */ + LFGuildStore GetGuildsMatchingSetting(LFGuildPlayer& settings, TeamId faction); + + /// Provided a player DB guid and a guild DB guid, determines if a pending request is filed with these keys. + bool HasRequest(uint32 playerId, uint32 guildId); + + /// Counts the amount of pending membership requests, given the player's db guid. + uint8 CountRequestsFromPlayer(uint32 playerId); + + void SendApplicantListUpdate(Guild& guild); + void SendMembershipRequestListUpdate(Player& player); +}; + +#define sGuildFinderMgr ACE_Singleton<GuildFinderMgr, ACE_Null_Mutex>::instance() + +#endif // __TRINITY_GUILDFINDER_H diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 32ed1d2b27f..70c1bc5955b 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -30,6 +30,7 @@ #include "Chat.h" #include "Group.h" #include "Guild.h" +#include "GuildFinderMgr.h" #include "Language.h" #include "Log.h" #include "Opcodes.h" @@ -685,7 +686,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte std::string IP_str = GetRemoteAddress(); sLog->outInfo(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow()); sScriptMgr->OnPlayerCreate(&newChar); - sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass()); + sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass(), newChar.getLevel()); newChar.CleanupsBeforeDelete(); delete createInfo; @@ -742,7 +743,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket & recvData) std::string IP_str = GetRemoteAddress(); sLog->outInfo(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), GUID_LOPART(guid)); sScriptMgr->OnPlayerDelete(guid); - sWorld->DeleteCharaceterNameData(GUID_LOPART(guid)); + sWorld->DeleteCharacterNameData(GUID_LOPART(guid)); if (sLog->ShouldLog(LOG_FILTER_PLAYER_DUMP, LOG_LEVEL_INFO)) // optimize GetPlayerDump call { @@ -751,6 +752,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket & recvData) sLog->outCharDump(dump.c_str(), GetAccountId(), GUID_LOPART(guid), name.c_str()); } + sGuildFinderMgr->RemoveAllMembershipRequestsFromPlayer(guid); Player::DeleteFromDB(guid, GetAccountId()); WorldPacket data(SMSG_CHAR_DELETE, 1); diff --git a/src/server/game/Handlers/GuildFinderHandler.cpp b/src/server/game/Handlers/GuildFinderHandler.cpp new file mode 100644 index 00000000000..facbd98ffac --- /dev/null +++ b/src/server/game/Handlers/GuildFinderHandler.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2008-2012 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 "WorldSession.h" +#include "WorldPacket.h" +#include "Object.h" +#include "SharedDefines.h" +#include "GuildFinderMgr.h" +#include "GuildMgr.h" + +void WorldSession::HandleGuildFinderAddRecruit(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_ADD_RECRUIT"); + + if (sGuildFinderMgr->GetAllMembershipRequestsForPlayer(GetPlayer()->GetGUIDLow()).size() == 10) + return; + + uint32 classRoles = 0; + uint32 availability = 0; + uint32 guildInterests = 0; + + recvPacket >> classRoles >> guildInterests >> availability; + + ObjectGuid guid; + guid[3] = recvPacket.ReadBit(); + guid[0] = recvPacket.ReadBit(); + guid[6] = recvPacket.ReadBit(); + guid[1] = recvPacket.ReadBit(); + uint16 commentLength = recvPacket.ReadBits(11); + guid[5] = recvPacket.ReadBit(); + guid[4] = recvPacket.ReadBit(); + guid[7] = recvPacket.ReadBit(); + uint8 nameLength = recvPacket.ReadBits(7); + guid[2] = recvPacket.ReadBit(); + + recvPacket.ReadByteSeq(guid[4]); + recvPacket.ReadByteSeq(guid[5]); + std::string comment = recvPacket.ReadString(commentLength); + std::string playerName = recvPacket.ReadString(nameLength); + recvPacket.ReadByteSeq(guid[7]); + recvPacket.ReadByteSeq(guid[2]); + recvPacket.ReadByteSeq(guid[0]); + recvPacket.ReadByteSeq(guid[6]); + recvPacket.ReadByteSeq(guid[1]); + recvPacket.ReadByteSeq(guid[3]); + + uint32 guildLowGuid = GUID_LOPART(uint64(guid)); + + if (!IS_GUILD_GUID(guid)) + return; + if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES) + return; + if (!(availability & ALL_WEEK) || availability > ALL_WEEK) + return; + if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS) + return; + + MembershipRequest request = MembershipRequest(GetPlayer()->GetGUIDLow(), guildLowGuid, availability, classRoles, guildInterests, comment, time(NULL)); + sGuildFinderMgr->AddMembershipRequest(guildLowGuid, request); +} + +void WorldSession::HandleGuildFinderBrowse(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_BROWSE"); + uint32 classRoles = 0; + uint32 availability = 0; + uint32 guildInterests = 0; + uint32 playerLevel = 0; // Raw player level (1-85), do they use MAX_FINDER_LEVEL when on level 85 ? + + recvPacket >> classRoles >> availability >> guildInterests >> playerLevel; + + if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES) + return; + if (!(availability & ALL_WEEK) || availability > ALL_WEEK) + return; + if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS) + return; + if (playerLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || playerLevel < 1) + return; + + Player* player = GetPlayer(); + + LFGuildPlayer settings(player->GetGUIDLow(), classRoles, availability, guildInterests, ANY_FINDER_LEVEL); + LFGuildStore guildList = sGuildFinderMgr->GetGuildsMatchingSetting(settings, player->GetTeamId()); + uint32 guildCount = guildList.size(); + + if (guildCount == 0) + { + WorldPacket packet(SMSG_LF_GUILD_BROWSE_UPDATED, 0); + player->SendDirectMessage(&packet); + return; + } + + ByteBuffer bufferData(65 * guildCount); + WorldPacket data(SMSG_LF_GUILD_BROWSE_UPDATED, 3 + guildCount * 65); // Estimated size + data.WriteBits(guildCount, 19); + + for (LFGuildStore::const_iterator itr = guildList.begin(); itr != guildList.end(); ++itr) + { + LFGuildSettings guildSettings = itr->second; + Guild* guild = sGuildMgr->GetGuildById(itr->first); + + ObjectGuid guildGUID = ObjectGuid(guild->GetGUID()); + + data.WriteBit(guildGUID[7]); + data.WriteBit(guildGUID[5]); + data.WriteBits(guild->GetName().size(), 8); + data.WriteBit(guildGUID[0]); + data.WriteBits(guildSettings.GetComment().size(), 11); + data.WriteBit(guildGUID[4]); + data.WriteBit(guildGUID[1]); + data.WriteBit(guildGUID[2]); + data.WriteBit(guildGUID[6]); + data.WriteBit(guildGUID[3]); + + bufferData << int32(guild->GetEmblemInfo().GetColor()); + bufferData << int32(guild->GetEmblemInfo().GetBorderStyle()); // Guessed + bufferData << int32(guild->GetEmblemInfo().GetStyle()); + + bufferData.WriteString(guildSettings.GetComment()); + + bufferData << uint8(0); // Cached ? Idk + + bufferData.WriteByteSeq(guildGUID[5]); + + bufferData << uint32(guildSettings.GetInterests()); // Guild Interests + + bufferData.WriteByteSeq(guildGUID[6]); + bufferData.WriteByteSeq(guildGUID[4]); + + bufferData << guild->GetLevel(); + + bufferData.WriteString(guild->GetName()); + + bufferData << int32(0); // guild->GetAchievementMgr().GetAchievementPoints() + + bufferData.WriteByteSeq(guildGUID[7]); + + bufferData << uint8(sGuildFinderMgr->HasRequest(player->GetGUIDLow(), guild->GetGUID())); // Request pending + + bufferData.WriteByteSeq(guildGUID[2]); + bufferData.WriteByteSeq(guildGUID[0]); + + bufferData << uint32(guildSettings.GetAvailability()); + + bufferData.WriteByteSeq(guildGUID[1]); + + bufferData << int32(guild->GetEmblemInfo().GetBackgroundColor()); + bufferData << uint32(0); // Unk Int 2 (+ 128) // Always 0 or 1 + bufferData << int32(guild->GetEmblemInfo().GetBorderColor()); + bufferData << uint32(guildSettings.GetClassRoles()); + + bufferData.WriteByteSeq(guildGUID[3]); + bufferData << int32(guild->GetMembersCount()); + } + + data.FlushBits(); + data.append(bufferData); + + player->SendDirectMessage(&data); +} + +void WorldSession::HandleGuildFinderDeclineRecruit(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_DECLINE_RECRUIT"); + + ObjectGuid playerGuid; + + playerGuid[1] = recvPacket.ReadBit(); + playerGuid[4] = recvPacket.ReadBit(); + playerGuid[5] = recvPacket.ReadBit(); + playerGuid[2] = recvPacket.ReadBit(); + playerGuid[6] = recvPacket.ReadBit(); + playerGuid[7] = recvPacket.ReadBit(); + playerGuid[0] = recvPacket.ReadBit(); + playerGuid[3] = recvPacket.ReadBit(); + + recvPacket.ReadByteSeq(playerGuid[5]); + recvPacket.ReadByteSeq(playerGuid[7]); + recvPacket.ReadByteSeq(playerGuid[2]); + recvPacket.ReadByteSeq(playerGuid[3]); + recvPacket.ReadByteSeq(playerGuid[4]); + recvPacket.ReadByteSeq(playerGuid[1]); + recvPacket.ReadByteSeq(playerGuid[0]); + recvPacket.ReadByteSeq(playerGuid[6]); + + if (!IS_PLAYER_GUID(playerGuid)) + return; + + sGuildFinderMgr->RemoveMembershipRequest(GUID_LOPART(playerGuid), GetPlayer()->GetGuildId()); +} + +void WorldSession::HandleGuildFinderGetApplications(WorldPacket& /*recvPacket*/) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_GET_APPLICATIONS"); // Empty opcode + + std::list<MembershipRequest> applicatedGuilds = sGuildFinderMgr->GetAllMembershipRequestsForPlayer(GetPlayer()->GetGUIDLow()); + uint32 applicationsCount = applicatedGuilds.size(); + WorldPacket data(SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED, 7 + 54 * applicationsCount); + data.WriteBits(applicationsCount, 20); + + if (applicationsCount > 0) + { + ByteBuffer bufferData(54 * applicationsCount); + for (std::list<MembershipRequest>::const_iterator itr = applicatedGuilds.begin(); itr != applicatedGuilds.end(); ++itr) + { + Guild* guild = sGuildMgr->GetGuildById(itr->GetGuildId()); + LFGuildSettings guildSettings = sGuildFinderMgr->GetGuildSettings(itr->GetGuildId()); + MembershipRequest request = *itr; + + ObjectGuid guildGuid = ObjectGuid(guild->GetGUID()); + + data.WriteBit(guildGuid[1]); + data.WriteBit(guildGuid[0]); + data.WriteBit(guildGuid[5]); + data.WriteBits(request.GetComment().size(), 11); + data.WriteBit(guildGuid[3]); + data.WriteBit(guildGuid[7]); + data.WriteBit(guildGuid[4]); + data.WriteBit(guildGuid[6]); + data.WriteBit(guildGuid[2]); + data.WriteBits(guild->GetName().size(), 8); + + bufferData.WriteByteSeq(guildGuid[2]); + bufferData.WriteString(request.GetComment()); + bufferData.WriteByteSeq(guildGuid[5]); + bufferData.WriteString(guild->GetName()); + + bufferData << uint32(guildSettings.GetAvailability()); + bufferData << uint32(request.GetExpiryTime() - time(NULL)); // Time left to application expiry (seconds) + + bufferData.WriteByteSeq(guildGuid[0]); + bufferData.WriteByteSeq(guildGuid[6]); + bufferData.WriteByteSeq(guildGuid[3]); + bufferData.WriteByteSeq(guildGuid[7]); + + bufferData << uint32(guildSettings.GetClassRoles()); + + bufferData.WriteByteSeq(guildGuid[4]); + bufferData.WriteByteSeq(guildGuid[1]); + + bufferData << uint32(time(NULL) - request.GetSubmitTime()); // Time since application (seconds) + bufferData << uint32(guildSettings.GetInterests()); + } + + data.FlushBits(); + data.append(bufferData); + } + data << uint32(10 - sGuildFinderMgr->CountRequestsFromPlayer(GetPlayer()->GetGUIDLow())); // Applications count left + + GetPlayer()->SendDirectMessage(&data); +} + +// Lists all recruits for a guild - Misses times +void WorldSession::HandleGuildFinderGetRecruits(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_GET_RECRUITS"); + + uint32 unkTime = 0; + recvPacket >> unkTime; + + Player* player = GetPlayer(); + if (!player->GetGuildId()) + return; + + std::vector<MembershipRequest> recruitsList = sGuildFinderMgr->GetAllMembershipRequestsForGuild(player->GetGuildId()); + uint32 recruitCount = recruitsList.size(); + + ByteBuffer dataBuffer(53 * recruitCount); + WorldPacket data(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, 7 + 26 * recruitCount + 53 * recruitCount); + data.WriteBits(recruitCount, 20); + + for (std::vector<MembershipRequest>::const_iterator itr = recruitsList.begin(); itr != recruitsList.end(); ++itr) + { + MembershipRequest request = *itr; + ObjectGuid playerGuid(MAKE_NEW_GUID(request.GetPlayerGUID(), 0, HIGHGUID_PLAYER)); + + data.WriteBits(request.GetComment().size(), 11); + data.WriteBit(playerGuid[2]); + data.WriteBit(playerGuid[4]); + data.WriteBit(playerGuid[3]); + data.WriteBit(playerGuid[7]); + data.WriteBit(playerGuid[0]); + data.WriteBits(request.GetName().size(), 7); + data.WriteBit(playerGuid[5]); + data.WriteBit(playerGuid[1]); + data.WriteBit(playerGuid[6]); + + dataBuffer.WriteByteSeq(playerGuid[4]); + + dataBuffer << int32(time(NULL) <= request.GetExpiryTime()); + + dataBuffer.WriteByteSeq(playerGuid[3]); + dataBuffer.WriteByteSeq(playerGuid[0]); + dataBuffer.WriteByteSeq(playerGuid[1]); + + dataBuffer << int32(request.GetLevel()); + + dataBuffer.WriteByteSeq(playerGuid[6]); + dataBuffer.WriteByteSeq(playerGuid[7]); + dataBuffer.WriteByteSeq(playerGuid[2]); + + dataBuffer << int32(time(NULL) - request.GetSubmitTime()); // Time in seconds since application submitted. + dataBuffer << int32(request.GetAvailability()); + dataBuffer << int32(request.GetClassRoles()); + dataBuffer << int32(request.GetInterests()); + dataBuffer << int32(request.GetExpiryTime() - time(NULL)); // TIme in seconds until application expires. + + dataBuffer.WriteString(request.GetName()); + dataBuffer.WriteString(request.GetComment()); + + dataBuffer << int32(request.GetClass()); + + dataBuffer.WriteByteSeq(playerGuid[5]); + } + + data.FlushBits(); + data.append(dataBuffer); + data << uint32(time(NULL)); // Unk time + + player->SendDirectMessage(&data); +} + +void WorldSession::HandleGuildFinderPostRequest(WorldPacket& /*recvPacket*/) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_POST_REQUEST"); // Empty opcode + + Player* player = GetPlayer(); + + if (!player->GetGuildId()) // Player must be in guild + return; + + bool isGuildMaster = true; + if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId())) + if (guild->GetLeaderGUID() != player->GetGUID()) + isGuildMaster = false; + + LFGuildSettings settings = sGuildFinderMgr->GetGuildSettings(player->GetGuildId()); + + WorldPacket data(SMSG_LF_GUILD_POST_UPDATED, 35); + data.WriteBit(isGuildMaster); // Guessed + + if (isGuildMaster) + { + data.WriteBit(settings.IsListed()); + data.WriteBits(settings.GetComment().size(), 11); + data << uint32(settings.GetLevel()); + data.WriteString(settings.GetComment()); + data << uint32(0); // Unk Int32 + data << uint32(settings.GetAvailability()); + data << uint32(settings.GetClassRoles()); + data << uint32(settings.GetInterests()); + } + else + data.FlushBits(); + player->SendDirectMessage(&data); +} + +void WorldSession::HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_REMOVE_RECRUIT"); + + ObjectGuid guildGuid; + + guildGuid[0] = recvPacket.ReadBit(); + guildGuid[4] = recvPacket.ReadBit(); + guildGuid[3] = recvPacket.ReadBit(); + guildGuid[5] = recvPacket.ReadBit(); + guildGuid[7] = recvPacket.ReadBit(); + guildGuid[6] = recvPacket.ReadBit(); + guildGuid[2] = recvPacket.ReadBit(); + guildGuid[1] = recvPacket.ReadBit(); + + recvPacket.ReadByteSeq(guildGuid[4]); + recvPacket.ReadByteSeq(guildGuid[0]); + recvPacket.ReadByteSeq(guildGuid[3]); + recvPacket.ReadByteSeq(guildGuid[6]); + recvPacket.ReadByteSeq(guildGuid[5]); + recvPacket.ReadByteSeq(guildGuid[1]); + recvPacket.ReadByteSeq(guildGuid[2]); + recvPacket.ReadByteSeq(guildGuid[7]); + + if (!IS_GUILD_GUID(guildGuid)) + return; + + sGuildFinderMgr->RemoveMembershipRequest(GetPlayer()->GetGUIDLow(), GUID_LOPART(guildGuid)); +} + +// Sent any time a guild master sets an option in the interface and when listing / unlisting his guild +void WorldSession::HandleGuildFinderSetGuildPost(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LF_GUILD_SET_GUILD_POST"); + + uint32 classRoles = 0; + uint32 availability = 0; + uint32 guildInterests = 0; + uint32 level = 0; + + recvPacket >> level >> availability >> guildInterests >> classRoles; + // Level sent is zero if untouched, force to any (from interface). Idk why + if (!level) + level = ANY_FINDER_LEVEL; + + uint16 length = recvPacket.ReadBits(11); + bool listed = recvPacket.ReadBit(); + std::string comment = recvPacket.ReadString(length); + + if (!(classRoles & GUILDFINDER_ALL_ROLES) || classRoles > GUILDFINDER_ALL_ROLES) + return; + if (!(availability & ALL_WEEK) || availability > ALL_WEEK) + return; + if (!(guildInterests & ALL_INTERESTS) || guildInterests > ALL_INTERESTS) + return; + if (!(level & ALL_GUILDFINDER_LEVELS) || level > ALL_GUILDFINDER_LEVELS) + return; + + Player* player = GetPlayer(); + + if (!player->GetGuildId()) // Player must be in guild + return; + + if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId())) // Player must be guild master + if (guild->GetLeaderGUID() != player->GetGUID()) + return; + + LFGuildSettings settings(listed, player->GetTeamId(), player->GetGuildId(), classRoles, availability, guildInterests, level, comment); + sGuildFinderMgr->SetGuildSettings(player->GetGuildId(), settings); +} diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 3ed5c0fe7f8..b1ef5bcb704 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -261,7 +261,7 @@ void InitOpcodes() DEFINE_OPCODE_HANDLER(CMSG_GUILD_DECLINE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDeclineOpcode ); DEFINE_OPCODE_HANDLER(CMSG_GUILD_DEL_RANK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDelRankOpcode ); DEFINE_OPCODE_HANDLER(CMSG_GUILD_DEMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDemoteOpcode ); - DEFINE_OPCODE_HANDLER(CMSG_GUILD_DISBAND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDisbandOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_GUILD_DISBAND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildDisbandOpcode ); DEFINE_OPCODE_HANDLER(CMSG_GUILD_EVENT_LOG_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildEventLogQueryOpcode ); DEFINE_OPCODE_HANDLER(CMSG_GUILD_INFO_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildChangeInfoTextOpcode ); DEFINE_OPCODE_HANDLER(CMSG_GUILD_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildInviteOpcode ); @@ -310,14 +310,14 @@ void InitOpcodes() DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_COMMENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_ROLES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetRolesOpcode ); DEFINE_OPCODE_HANDLER(CMSG_LFG_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgTeleportOpcode ); - DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_ADD_RECRUIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_BROWSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_DECLINE_RECRUIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_APPLICATIONS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_RECRUITS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_POST_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_REMOVE_RECRUIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_SET_GUILD_POST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_ADD_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderAddRecruit ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_BROWSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderBrowse ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_DECLINE_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderDeclineRecruit ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_APPLICATIONS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderGetApplications); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_GET_RECRUITS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderGetRecruits ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_POST_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderPostRequest ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_REMOVE_RECRUIT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderRemoveRecruit ); + DEFINE_OPCODE_HANDLER(CMSG_LF_GUILD_SET_GUILD_POST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderSetGuildPost ); DEFINE_OPCODE_HANDLER(CMSG_LIST_INVENTORY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListInventoryOpcode ); DEFINE_OPCODE_HANDLER(CMSG_LOAD_SCREEN, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleLoadScreenOpcode ); DEFINE_OPCODE_HANDLER(CMSG_LOGOUT_CANCEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode ); @@ -940,13 +940,13 @@ void InitOpcodes() DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_SEARCH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_LFG_UPDATE_STATUS_NONE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICANT_LIST_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_BROWSE_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_COMMAND_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_POST_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICANT_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_BROWSE_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_POST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_LF_GUILD_RECRUIT_LIST_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_LIST_INVENTORY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_LOGIN_SETTIMESPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index b948ce76ca6..a9594fa44a6 100755 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -312,7 +312,6 @@ enum Opcodes CMSG_LF_GUILD_DECLINE_RECRUIT = 0x1031, CMSG_LF_GUILD_GET_APPLICATIONS = 0x1230, CMSG_LF_GUILD_GET_RECRUITS = 0x3230, - CMSG_LF_GUILD_JOIN = 0x0000, CMSG_LF_GUILD_POST_REQUEST = 0x3237, CMSG_LF_GUILD_REMOVE_RECRUIT = 0x3027, CMSG_LF_GUILD_SET_GUILD_POST = 0x0448, @@ -1024,7 +1023,6 @@ enum Opcodes SMSG_LF_GUILD_MEMBERSHIP_LIST_UPDATED = 0x1CA5, SMSG_LF_GUILD_POST_UPDATED = 0x35B7, SMSG_LF_GUILD_RECRUIT_LIST_UPDATED = 0x1CB2, - SMSG_LF_GUILD_SEARCH_RESULT = 0x0000, SMSG_LIST_INVENTORY = 0x7CB0, SMSG_LOAD_CUF_PROFILES = 0x50B1, SMSG_LOGIN_SETTIMESPEED = 0x4D15, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index a7ab19f393a..1db1399e45f 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -245,7 +245,7 @@ class WorldSession bool IsAddonRegistered(const std::string& prefix) const; void ReadMovementInfo(WorldPacket& data, MovementInfo* mi); - void WriteMovementInfo(WorldPacket &data, MovementInfo* mi); + void WriteMovementInfo(WorldPacket& data, MovementInfo* mi); void SendPacket(WorldPacket const* packet, bool forced = false); void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3); @@ -597,6 +597,15 @@ class WorldSession void HandleGuildRequestMaxDailyXP(WorldPacket& recvPacket); void HandleAutoDeclineGuildInvites(WorldPacket& recvPacket); + void HandleGuildFinderAddRecruit(WorldPacket& recvPacket); + void HandleGuildFinderBrowse(WorldPacket& recvPacket); + void HandleGuildFinderDeclineRecruit(WorldPacket& recvPacket); + void HandleGuildFinderGetApplications(WorldPacket& recvPacket); + void HandleGuildFinderGetRecruits(WorldPacket& recvPacket); + void HandleGuildFinderPostRequest(WorldPacket& recvPacket); + void HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket); + void HandleGuildFinderSetGuildPost(WorldPacket& recvPacket); + void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket); void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket); void HandleActivateTaxiOpcode(WorldPacket& recvPacket); diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index ae05cb4e8eb..86cc42fba42 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -462,6 +462,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s uint8 gender = GENDER_NONE; uint8 race = RACE_NONE; uint8 playerClass = 0; + uint8 level = 1; SQLTransaction trans = CharacterDatabase.BeginTransaction(); while (!feof(fin)) @@ -536,6 +537,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s race = uint8(atol(getnth(line, 4).c_str())); playerClass = uint8(atol(getnth(line, 5).c_str())); gender = uint8(atol(getnth(line, 6).c_str())); + level = uint8(atol(getnth(line, 7).c_str())); if (name == "") { // check if the original name already exists @@ -679,7 +681,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s CharacterDatabase.CommitTransaction(trans); // in case of name conflict player has to rename at login anyway - sWorld->AddCharacterNameData(guid, name, gender, race, playerClass); + sWorld->AddCharacterNameData(guid, name, gender, race, playerClass, level); sObjectMgr->_hiItemGuid += items.size(); sObjectMgr->_mailId += mails.size(); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 92dd103f79d..204e90053ad 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -39,6 +39,7 @@ #include "ObjectMgr.h" #include "ArenaTeamMgr.h" #include "GuildMgr.h" +#include "GuildFinderMgr.h" #include "TicketMgr.h" #include "SpellMgr.h" #include "GroupMgr.h" @@ -1572,6 +1573,8 @@ void World::SetInitialWorldSettings() sGuildMgr->LoadGuilds(); + sGuildFinderMgr->LoadFromDB(); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading ArenaTeams..."); sArenaTeamMgr->LoadArenaTeams(); @@ -2955,7 +2958,7 @@ void World::LoadCharacterNameData() { sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading character name data"); - QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class FROM characters WHERE deleteDate IS NULL"); + QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class, level FROM characters WHERE deleteDate IS NULL"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, "No character name data loaded, empty query"); @@ -2968,20 +2971,21 @@ void World::LoadCharacterNameData() { Field* fields = result->Fetch(); AddCharacterNameData(fields[0].GetUInt32(), fields[1].GetString(), - fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/); + fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/, fields[5].GetUInt8()); ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loaded name data for %u characters", count); } -void World::AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass) +void World::AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level) { CharacterNameData& data = _characterNameDataMap[guid]; data.m_name = name; data.m_race = race; data.m_gender = gender; data.m_class = playerClass; + data.m_level = level; } void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender /*= GENDER_NONE*/, uint8 race /*= RACE_NONE*/) @@ -2999,6 +3003,15 @@ void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 itr->second.m_race = race; } +void World::UpdateCharacterNameDataLevel(uint32 guid, uint8 level) +{ + std::map<uint32, CharacterNameData>::iterator itr = _characterNameDataMap.find(guid); + if (itr == _characterNameDataMap.end()) + return; + + itr->second.m_level = level; +} + CharacterNameData const* World::GetCharacterNameData(uint32 guid) const { std::map<uint32, CharacterNameData>::const_iterator itr = _characterNameDataMap.find(guid); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index f0f5e3f723b..b8243cb0531 100755 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -555,6 +555,7 @@ struct CharacterNameData uint8 m_class; uint8 m_race; uint8 m_gender; + uint8 m_level; }; /// The World @@ -776,9 +777,10 @@ class World bool isEventKillStart; CharacterNameData const* GetCharacterNameData(uint32 guid) const; - void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass); + void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level); void UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE); - void DeleteCharaceterNameData(uint32 guid) { _characterNameDataMap.erase(guid); } + void UpdateCharacterNameDataLevel(uint32 guid, uint8 level); + void DeleteCharacterNameData(uint32 guid) { _characterNameDataMap.erase(guid); } uint32 GetCleaningFlags() const { return m_CleaningFlags; } void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; } |
