/*
* Copyright (C) 2008-2015 TrinityCore
*
* 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 .
*/
#include "ObjectMgr.h"
#include "GuildFinderMgr.h"
#include "GuildMgr.h"
#include "GuildFinderPackets.h"
#include "World.h"
GuildFinderMgr::GuildFinderMgr()
{
}
GuildFinderMgr::~GuildFinderMgr()
{
}
void GuildFinderMgr::LoadFromDB()
{
LoadGuildSettings();
LoadMembershipRequests();
}
void GuildFinderMgr::LoadGuildSettings()
{
TC_LOG_INFO("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)
{
TC_LOG_INFO("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();
ObjectGuid guildId = ObjectGuid::Create(fields[0].GetUInt64());
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_NEUTRAL;
if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(fields[7].GetUInt8()))
guildTeam = (TeamId)raceEntry->TeamID;
LFGuildSettings settings(listed, guildTeam, guildId, classRoles, availability, interests, level, comment);
_guildSettings[guildId] = settings;
++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u guild finder guild-related settings in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
}
void GuildFinderMgr::LoadMembershipRequests()
{
TC_LOG_INFO("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)
{
TC_LOG_INFO("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();
ObjectGuid guildId = ObjectGuid::Create(fields[0].GetUInt64());
ObjectGuid playerId = ObjectGuid::Create(fields[1].GetUInt64());
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));
_membershipRequestsByGuild[guildId][playerId] = request;
_membershipRequestsByPlayer[playerId][guildId] = request;
++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u guild finder membership requests in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
}
void GuildFinderMgr::AddMembershipRequest(ObjectGuid const& guildGuid, MembershipRequest const& request)
{
_membershipRequestsByGuild[guildGuid][request.GetPlayerGUID()] = request;
_membershipRequestsByPlayer[request.GetPlayerGUID()][guildGuid] = request;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GUILD_FINDER_APPLICANT);
stmt->setUInt64(0, request.GetGuildGuid().GetCounter());
stmt->setUInt64(1, request.GetPlayerGUID().GetCounter());
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(request.GetPlayerGUID()))
SendMembershipRequestListUpdate(player);
// Notify the guild master and officers the list changed
if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
SendApplicantListUpdate(guild);
}
void GuildFinderMgr::RemoveAllMembershipRequestsFromPlayer(ObjectGuid const& playerId)
{
auto playerItr = _membershipRequestsByPlayer.find(playerId);
if (playerItr == _membershipRequestsByPlayer.end())
return;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
for (auto& guildRequestPair : playerItr->second)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
stmt->setUInt64(0, guildRequestPair.first.GetCounter());
stmt->setUInt64(1, playerId.GetCounter());
trans->Append(stmt);
// Notify the guild master and officers the list changed
if (Guild* guild = sGuildMgr->GetGuildByGuid(guildRequestPair.first))
SendApplicantListUpdate(guild);
auto guildItr = _membershipRequestsByGuild.find(guildRequestPair.first);
if (guildItr == _membershipRequestsByGuild.end())
continue;
guildItr->second.erase(playerId);
if (guildItr->second.empty())
_membershipRequestsByGuild.erase(guildItr);
}
CharacterDatabase.CommitTransaction(trans);
_membershipRequestsByPlayer.erase(playerItr);
}
void GuildFinderMgr::RemoveMembershipRequest(ObjectGuid const& playerId, ObjectGuid const& guildId)
{
auto guildItr = _membershipRequestsByGuild.find(guildId);
if (guildItr != _membershipRequestsByGuild.end())
{
guildItr->second.erase(playerId);
if (guildItr->second.empty())
_membershipRequestsByGuild.erase(guildItr);
}
auto playerItr = _membershipRequestsByPlayer.find(playerId);
if (playerItr != _membershipRequestsByPlayer.end())
{
playerItr->second.erase(guildId);
if (playerItr->second.empty())
_membershipRequestsByPlayer.erase(playerItr);
}
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
stmt->setUInt64(0, guildId.GetCounter());
stmt->setUInt64(1, playerId.GetCounter());
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
// Notify the applicant his submittion has been removed
if (Player* player = ObjectAccessor::FindPlayer(playerId))
SendMembershipRequestListUpdate(player);
// Notify the guild master and officers the list changed
if (Guild* guild = sGuildMgr->GetGuildByGuid(guildId))
SendApplicantListUpdate(guild);
}
std::vector GuildFinderMgr::GetAllMembershipRequestsForPlayer(ObjectGuid const& playerGuid)
{
std::vector resultSet;
auto playerItr = _membershipRequestsByPlayer.find(playerGuid);
if (playerItr == _membershipRequestsByPlayer.end())
return resultSet;
resultSet.reserve(playerItr->second.size());
for (auto const& guildRequestPair : playerItr->second)
resultSet.push_back(&guildRequestPair.second);
return resultSet;
}
uint8 GuildFinderMgr::CountRequestsFromPlayer(ObjectGuid const& playerId)
{
auto playerItr = _membershipRequestsByPlayer.find(playerId);
return playerItr != _membershipRequestsByPlayer.end() ? playerItr->second.size() : 0;
}
std::vector GuildFinderMgr::GetGuildsMatchingSetting(LFGuildPlayer& settings, TeamId faction)
{
std::vector resultSet;
for (LFGuildStore::const_iterator itr = _guildSettings.begin(); itr != _guildSettings.end(); ++itr)
{
LFGuildSettings const& guildSettings = itr->second;
if (!guildSettings.IsListed())
continue;
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.push_back(&itr->second);
}
return resultSet;
}
bool GuildFinderMgr::HasRequest(ObjectGuid const& playerId, ObjectGuid const& guildId)
{
auto guildItr = _membershipRequestsByGuild.find(guildId);
if (guildItr == _membershipRequestsByGuild.end())
return false;
return guildItr->second.count(playerId) > 0;
}
void GuildFinderMgr::SetGuildSettings(ObjectGuid const& guildGuid, LFGuildSettings const& settings)
{
_guildSettings[guildGuid] = settings;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GUILD_FINDER_GUILD_SETTINGS);
stmt->setUInt64(0, settings.GetGUID().GetCounter());
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(ObjectGuid const& guildId)
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
auto guildItr = _membershipRequestsByGuild.find(guildId);
if (guildItr != _membershipRequestsByGuild.end())
{
for (auto playerRequestPair : guildItr->second)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_APPLICANT);
stmt->setUInt64(0, guildId.GetCounter());
stmt->setUInt64(1, playerRequestPair.first.GetCounter());
trans->Append(stmt);
auto playerItr = _membershipRequestsByPlayer.find(playerRequestPair.first);
if (playerItr != _membershipRequestsByPlayer.end())
{
playerItr->second.erase(guildId);
if (playerItr->second.empty())
_membershipRequestsByPlayer.erase(playerItr);
}
// Notify the applicant his submition has been removed
if (Player* player = ObjectAccessor::FindPlayer(playerRequestPair.first))
SendMembershipRequestListUpdate(player);
}
}
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS);
stmt->setUInt64(0, guildId.GetCounter());
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
_membershipRequestsByGuild.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->GetGuildByGuid(guildId))
SendApplicantListUpdate(guild);
}
void GuildFinderMgr::SendApplicantListUpdate(Guild* guild)
{
WorldPackets::GuildFinder::LFGuildApplicantListChanged applicantListChanged;
guild->BroadcastPacketToRank(applicantListChanged.Write(), GR_OFFICER);
if (Player* player = ObjectAccessor::FindPlayer(guild->GetLeaderGUID()))
player->SendDirectMessage(applicantListChanged.GetRawPacket());
}
void GuildFinderMgr::SendMembershipRequestListUpdate(Player* player)
{
player->SendDirectMessage(WorldPackets::GuildFinder::LFGuildApplicationsListChanged().Write());
}