/* * Ascent MMORPG Server * Copyright (C) 2005-2007 Ascent Team * * 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 3 of the License, or * 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 "StdAfx.h" initialiseSingleton( SocialMgr ); SocialMgr::SocialMgr() { m_isInFriendList.clear(); m_hasInFriendList.clear(); m_isInIgnoreList.clear(); m_hasInIgnoreList.clear(); m_needsBlockNotice.clear(); } SocialMgr::~SocialMgr() { std::map*>::iterator iter; for(iter = m_isInFriendList.begin(); iter != m_isInFriendList.end(); ++iter) { delete iter->second; } m_isInFriendList.clear(); for(iter = m_hasInFriendList.begin(); iter != m_hasInFriendList.end(); ++iter) { delete iter->second; } m_hasInFriendList.clear(); for(iter = m_isInIgnoreList.begin(); iter != m_isInIgnoreList.end(); ++iter) { delete iter->second; } m_isInIgnoreList.clear(); for(iter = m_hasInIgnoreList.begin(); iter != m_hasInIgnoreList.end(); ++iter) { delete iter->second; } m_hasInIgnoreList.clear(); for(iter = m_needsBlockNotice.begin(); iter != m_needsBlockNotice.end(); ++iter) { delete iter->second; } m_needsBlockNotice.clear(); } void SocialMgr::SendFriendList(Player* plr) { if(!plr) return; WorldPacket data( SMSG_FRIEND_LIST , 512 ); uint64 plrguid = plr->GetGUID(); std::map*>::iterator fItr = m_hasInFriendList.find(plrguid); if( fItr == m_hasInFriendList.end() ) { data << (uint8)0; if(plr->GetSession()) plr->GetSession()->SendPacket( &data ); return; } std::set* fList = fItr->second; std::set::iterator itr; Player* pFriend = NULL; bool isGm = (plr->GetSession()->GetPermissionCount() > 0); data << (uint8)fList->size(); for(itr = fList->begin(); itr != fList->end(); itr++) { data << uint64(*itr); pFriend = objmgr.GetPlayer( *itr ); if(pFriend && (!pFriend->m_isGmInvisible || isGm)) data << uint8(1) << (uint32)pFriend->GetZoneId() << (uint32)pFriend->getLevel() << (uint32)pFriend->getClass(); else data << uint8(0); } plr->GetSession()->SendPacket( &data ); } void SocialMgr::SendIgnoreList(Player* plr) { if(!plr) return; WorldPacket data( SMSG_IGNORE_LIST, 512 ); uint64 plrguid = plr->GetGUID(); std::map*>::iterator iItr; iItr = m_hasInIgnoreList.find(plrguid); if( iItr == m_hasInIgnoreList.end() ) { data << (uint8)0; if(plr->GetSession()) plr->GetSession()->SendPacket( &data ); return; } std::set* iList = iItr->second; std::set::iterator itr; data << (uint8)iList->size(); for(itr = iList->begin(); itr != iList->end(); itr++) { data << uint64(*itr); } plr->GetSession()->SendPacket( &data ); } void SocialMgr::SendUpdateToFriends(Player* plr) { if(!plr) return; std::map*>::iterator Itr = m_isInFriendList.find(plr->GetGUID()); if(Itr == m_isInFriendList.end()) return; std::set* iList = Itr->second; std::set::iterator itr; Player* cPlayer = NULL; for(itr = iList->begin(); itr != iList->end(); itr++) { cPlayer = objmgr.GetPlayer(*itr); if(cPlayer) SendFriendList(cPlayer); } } void SocialMgr::AddFriend(Player* plr, std::string friendName) { if(!plr) return; WorldPacket data( SMSG_FRIEND_STATUS, 22 ); PlayerInfo* playerInfo = objmgr.GetPlayerInfo(plr->GetGUID()); PlayerInfo* friendInfo = objmgr.GetPlayerInfoByName(friendName); if(playerInfo == NULL) { // We shouldn't get here data << (uint8)FRIEND_DB_ERROR; plr->GetSession()->SendPacket( &data ); return; } if( friendInfo == NULL) { sLog.outDetail("WORLD: Guid of %s not found ", friendName.c_str() ); data << (uint8)FRIEND_NOT_FOUND; plr->GetSession()->SendPacket( &data ); return; } if( friendInfo->team != playerInfo->team ) { sLog.outDebug("SocialMgr: %s tried to add an ennemy to his friendlist", plr->GetName()); data << (uint8)FRIEND_ENEMY << (uint64)friendInfo->guid; plr->GetSession()->SendPacket( &data ); return; } uint64 pGuid = playerInfo->guid; uint64 fGuid = friendInfo->guid; Player *pFriend = objmgr.GetPlayer(fGuid); if ( pGuid == fGuid ) { sLog.outDebug("SocialMgr: %s tried to add himself to his friendlist", plr->GetName()); data << (uint8)FRIEND_SELF << (uint64)fGuid; plr->GetSession()->SendPacket(&data); return; } if( HasFriend(pGuid, fGuid) ) { sLog.outDebug("SocialMgr: %s tried to add someone who is already in his friendlist", plr->GetName()); data << (uint8)FRIEND_ALREADY << (uint64)fGuid; plr->GetSession()->SendPacket(&data); return; } sLog.outDebug("SocialMgr: %s added %s to his friendlist", playerInfo->name.c_str(), friendInfo->name.c_str()); if ( pFriend ) { data << (uint8)FRIEND_ADDED_ONLINE << (uint64)fGuid << (uint8)1; data << (uint32)pFriend->GetZoneId() << (uint32)pFriend->getLevel() << (uint32)pFriend->getClass(); } else data << (uint8)FRIEND_ADDED_OFFLINE << (uint64)friendInfo->guid; if( m_isInFriendList.find(fGuid) == m_isInFriendList.end() ) m_isInFriendList[fGuid] = new std::set; if( m_hasInFriendList.find(pGuid) == m_hasInFriendList.end() ) m_hasInFriendList[pGuid] = new std::set; m_hasInFriendList[pGuid]->insert(fGuid); m_isInFriendList[fGuid]->insert(pGuid); plr->GetSession()->SendPacket( &data ); CharacterDatabase.Execute("INSERT INTO social(guid,socialguid,flags) VALUES (%I64u,%I64u,'FRIEND')",pGuid,fGuid); } void SocialMgr::AddIgnore(Player* plr, std::string ignoreName) { if(!plr) return; WorldPacket data( SMSG_FRIEND_STATUS, 10 ); PlayerInfo* playerInfo = objmgr.GetPlayerInfo(plr->GetGUID()); PlayerInfo* ignoreInfo = objmgr.GetPlayerInfoByName(ignoreName); if (!ignoreInfo) { sLog.outDetail( "WORLD: Guid of %s not found ", ignoreName.c_str() ); data << (uint8)FRIEND_IGNORE_NOT_FOUND; plr->GetSession()->SendPacket( &data ); return; } if(playerInfo == NULL) { data << (uint8)FRIEND_DB_ERROR; plr->GetSession()->SendPacket( &data ); return; } uint64 pGuid = playerInfo->guid; uint64 iGuid = ignoreInfo->guid; if( pGuid == iGuid ) { sLog.outDebug("SocialMgr: %s tried to add himself to his friendlist", plr->GetName()); data << (uint8)FRIEND_IGNORE_SELF << (uint64)iGuid; plr->GetSession()->SendPacket(&data); return; } if( HasIgnore(playerInfo->guid, ignoreInfo->guid) ) { sLog.outDebug("SocialMgr: %s tried to add someone who is already in his ignorelist", plr->GetName()); data << (uint8)FRIEND_IGNORE_ALREADY << (uint64)iGuid; plr->GetSession()->SendPacket(&data); return; } sLog.outDebug("SocialMgr: %s added %s to his ignorelist", plr->GetName(), ignoreInfo->name.c_str()); data << (uint8)FRIEND_IGNORE_ADDED << (uint64)iGuid; if( m_isInIgnoreList.find(iGuid) == m_isInIgnoreList.end() ) m_isInIgnoreList[iGuid] = new std::set; if( m_hasInIgnoreList.find(pGuid) == m_hasInIgnoreList.end() ) m_hasInIgnoreList[pGuid] = new std::set; if( m_needsBlockNotice.find(iGuid) == m_needsBlockNotice.end() ) m_needsBlockNotice[iGuid] = new std::set; m_isInIgnoreList[iGuid]->insert(pGuid); m_hasInIgnoreList[pGuid]->insert(iGuid); m_needsBlockNotice[iGuid]->insert(pGuid); plr->GetSession()->SendPacket( &data ); CharacterDatabase.Execute("INSERT INTO social(guid,socialguid,flags,noticed) VALUES (%I64u,%I64u,'IGNORE',0)",pGuid,iGuid); } void SocialMgr::DelFriend(Player* plr, uint64 friendguid) { if(!plr) return; WorldPacket data(9); uint64 plrguid = plr->GetGUID(); sLog.outDebug("SocialMgr: %s is deleting friendguid %d from his friendlist", plr->GetName(), friendguid); std::map*>::iterator Itr; Itr = m_hasInFriendList.find(plrguid); if( Itr != m_hasInFriendList.end() ) Itr->second->erase( friendguid ); Itr = m_isInFriendList.find(friendguid); if( Itr != m_isInFriendList.end() ) Itr->second->erase( friendguid ); data.Initialize( SMSG_FRIEND_STATUS ); data << (uint8)FRIEND_REMOVED << (uint64)friendguid; plr->GetSession()->SendPacket( &data ); CharacterDatabase.Execute("DELETE FROM social WHERE guid=%I64u AND socialguid=%I64u AND flags='FRIEND'",plrguid,friendguid); } void SocialMgr::DelIgnore(Player* plr, uint64 ignoreguid) { if(!plr) return; WorldPacket data(9); uint64 plrguid = plr->GetGUID(); sLog.outDebug("SocialMgr: %s is deleting guid %d from his ignorelist", plr->GetName(), ignoreguid); std::map*>::iterator iItr; iItr = m_hasInIgnoreList.find(plrguid); if( iItr != m_hasInIgnoreList.end() ) iItr->second->erase(ignoreguid); iItr = m_isInIgnoreList.find(ignoreguid); if( iItr != m_isInIgnoreList.end() ) iItr->second->erase(plrguid); data.Initialize( SMSG_FRIEND_STATUS ); data << (uint8)FRIEND_IGNORE_REMOVED << (uint64)ignoreguid; plr->GetSession()->SendPacket( &data ); CharacterDatabase.Execute("DELETE FROM social WHERE guid=%I64u AND socialguid=%I64u AND flags='IGNORE'",plrguid,ignoreguid); } bool SocialMgr::IsFriend(uint64 plrguid, uint64 target) { std::map*>::iterator Itr = m_isInFriendList.find( target ); if( Itr == m_isInFriendList.end() ) return false; std::set::iterator sItr = Itr->second->find( plrguid ); if( sItr != Itr->second->end() ) return true; return false; } inline bool SocialMgr::HasFriend(uint64 plrguid, uint64 mfriend) { std::map*>::iterator Itr = m_hasInFriendList.find( plrguid ); if( Itr == m_hasInFriendList.end() ) return false; std::set::iterator sItr = Itr->second->find( mfriend ); if( sItr != Itr->second->end() ) return true; return false; } bool SocialMgr::IsIgnore(uint64 plrguid, uint64 target) { std::map*>::iterator Itr = m_isInIgnoreList.find(target); if( Itr == m_isInIgnoreList.end() ) return false; std::set::iterator sItr = Itr->second->find( plrguid ); if( sItr != Itr->second->end() ) return true; return false; } inline bool SocialMgr::HasIgnore(uint64 plrguid, uint64 mignore) { std::map*>::iterator Itr = m_hasInIgnoreList.find(plrguid); if( Itr == m_hasInIgnoreList.end() ) return false; std::set::iterator sItr = Itr->second->find( mignore ); if( sItr != Itr->second->end() ) return true; return false; } bool SocialMgr::HasIgnore(Player* plr, Player* mignore) { std::map*>::iterator Itr; uint64 plrguid = plr->GetGUID(); uint64 ignguid = mignore->GetGUID(); if( HasIgnore(plrguid, ignguid) ) { std::set::iterator iter; Itr = m_needsBlockNotice.find(ignguid); if( Itr != m_needsBlockNotice.end() ) { for(iter = Itr->second->begin(); iter != Itr->second->end(); iter++) { if( (*iter) == plrguid ) { std::stringstream ss; sChatHandler.SystemMessage(mignore->GetSession(), "%s is ignoring you, it isn't possible for you to whisper him/her.", plr->GetName()); Itr->second->erase( iter ); ss << "UPDATE social SET noticed=1 WHERE guid="<< plrguid <<" AND socialguid="<< ignguid <<" AND flags='IGNORE'"; CharacterDatabase.Execute( ss.str().c_str() ); return true; } } } return true; } return false; } inline void SocialMgr::SendOnlinePkt(Player* plr, SocialStr* pNfo) { if(!plr) return; WorldPacket data(SMSG_FRIEND_STATUS, 22); data << (uint8)FRIEND_ONLINE << (uint64)pNfo->pGuid << (uint8)1; data << pNfo->Area << (uint32)pNfo->Level << (uint32)pNfo->Class; plr->GetSession()->SendPacket( &data ); } inline void SocialMgr::SendOfflinePkt(Player* plr, uint64 fGuid) { if(!plr || !plr->GetSession()) return; WorldPacket data(SMSG_FRIEND_STATUS, 10); data << (uint8)FRIEND_OFFLINE << (uint64)fGuid << (uint8)0; plr->GetSession()->SendPacket( &data ); } void SocialMgr::LoggedIn(Player* plr) { if(!plr) return; SocialStr* pNfo = new SocialStr; pNfo->pGuid = plr->GetGUID(); std::map*>::iterator Itr = m_isInFriendList.find(pNfo->pGuid); if( Itr == m_isInFriendList.end() ) { delete pNfo; return; } pNfo->Level = plr->getLevel(); pNfo->Class = plr->getClass(); pNfo->Area = plr->GetZoneId(); std::set::iterator sItr = Itr->second->begin(); Player* fPlr = NULL; for( ; sItr != Itr->second->end(); sItr++ ) { fPlr = objmgr.GetPlayer(*sItr); if( fPlr ) SendOnlinePkt(fPlr, pNfo); } // naughty! delete pNfo; } void SocialMgr::LoggedOut(Player* plr) { if(!plr) return; uint64 plrguid = plr->GetGUID(); std::map*>::iterator Itr = m_isInFriendList.find(plrguid); if( Itr == m_isInFriendList.end() ) return; std::set::iterator sItr = Itr->second->begin(); Player* fPlr = NULL; for( ; sItr != Itr->second->end(); sItr++ ) { fPlr = objmgr.GetPlayer(*sItr); if( fPlr ) SendOfflinePkt(fPlr, plrguid); } } void SocialMgr::RemovePlayer(Player* plr) { if(!plr) return; uint64 plrguid = plr->GetGUID(); std::map*>::iterator Itr; std::map*>::iterator mItr; std::set::iterator sItr; Itr = m_isInFriendList.find( plrguid ); if( Itr != m_isInFriendList.end() ) { for(sItr = Itr->second->begin(); sItr != Itr->second->end(); sItr++) { mItr = m_hasInFriendList.find( *sItr ); if( mItr != m_hasInFriendList.end() ) mItr->second->erase( plrguid ); } delete Itr->second; m_isInFriendList.erase(Itr); } Itr = m_isInIgnoreList.find( plrguid ); if( Itr != m_isInIgnoreList.end() ) { for(sItr = Itr->second->begin(); sItr != Itr->second->end(); sItr++) { mItr = m_hasInIgnoreList.find( *sItr ); if( mItr != m_hasInIgnoreList.end() ) mItr->second->erase( plrguid ); } delete Itr->second; m_isInIgnoreList.erase(Itr); } Itr = m_needsBlockNotice.find(plrguid); if( Itr != m_needsBlockNotice.end() ) { delete Itr->second; m_needsBlockNotice.erase(Itr); } CharacterDatabase.Execute("DELETE FROM social WHERE guid=%d OR socialguid=%d", plr->GetGUIDLow(), plr->GetGUIDLow()); } void SocialMgr::LoadFromDB() { std::map*>::iterator Itr; uint64 plrguid = 0; uint64 friendguid = 0; uint64 ignoreguid = 0; bool noticed = false; QueryResult *result = CharacterDatabase.Query("SELECT guid,socialguid FROM social WHERE flags='FRIEND'"); if(result) { do { Field *field = result->Fetch(); plrguid = field[0].GetUInt64(); friendguid = field[1].GetUInt64(); if( m_isInFriendList.find(friendguid) == m_isInFriendList.end() ) m_isInFriendList[friendguid] = new std::set; if( m_hasInFriendList.find(plrguid) == m_hasInFriendList.end() ) m_hasInFriendList[plrguid] = new std::set; m_isInFriendList[friendguid]->insert(plrguid); m_hasInFriendList[plrguid]->insert(friendguid); } while( result->NextRow() ); delete result; } result = CharacterDatabase.Query("SELECT guid,socialguid,noticed FROM social WHERE flags='IGNORE'"); if(result) { do { Field *field = result->Fetch(); plrguid = field[0].GetUInt64(); ignoreguid = field[1].GetUInt64(); noticed = field[2].GetBool(); if( m_isInIgnoreList.find(ignoreguid) == m_isInIgnoreList.end() ) m_isInIgnoreList[ignoreguid] = new std::set; if( m_hasInIgnoreList.find(plrguid) == m_hasInIgnoreList.end() ) m_hasInIgnoreList[plrguid] = new std::set; if( !noticed ) { if( m_needsBlockNotice.find(ignoreguid) == m_needsBlockNotice.end() ) m_needsBlockNotice[ignoreguid] = new std::set; m_needsBlockNotice[ignoreguid]->insert(plrguid); } m_isInIgnoreList[ignoreguid]->insert(plrguid); m_hasInIgnoreList[plrguid]->insert(ignoreguid); } while( result->NextRow() ); delete result; } }