PageRenderTime 56ms CodeModel.GetById 22ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/newview/llcallingcard.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 904 lines | 689 code | 90 blank | 125 comment | 85 complexity | 6a9fbc1bac70948847a2a21a95981b46 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llcallingcard.cpp
  3. * @brief Implementation of the LLPreviewCallingCard class
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #if LL_WINDOWS
  28. #pragma warning( disable : 4800 ) // performance warning in <functional>
  29. #endif
  30. #include "llcallingcard.h"
  31. #include <vector>
  32. #include <algorithm>
  33. //#include <iterator>
  34. #include "indra_constants.h"
  35. #include "llavatarnamecache.h"
  36. #include "llcachename.h"
  37. #include "llstl.h"
  38. #include "lltimer.h"
  39. #include "lluuid.h"
  40. #include "message.h"
  41. #include "llagent.h"
  42. #include "llavatarnamecache.h"
  43. #include "llbutton.h"
  44. #include "llinventoryobserver.h"
  45. #include "llinventorymodel.h"
  46. #include "llnotifications.h"
  47. #include "llnotificationsutil.h"
  48. #include "llresmgr.h"
  49. #include "llslurl.h"
  50. #include "llimview.h"
  51. #include "llviewercontrol.h"
  52. #include "llviewernetwork.h"
  53. #include "llviewerobjectlist.h"
  54. #include "llviewerwindow.h"
  55. #include "llvoavatar.h"
  56. #include "llavataractions.h"
  57. ///----------------------------------------------------------------------------
  58. /// Local function declarations, constants, enums, and typedefs
  59. ///----------------------------------------------------------------------------
  60. class LLTrackingData
  61. {
  62. public:
  63. LLTrackingData(const LLUUID& avatar_id, const std::string& name);
  64. bool haveTrackingInfo();
  65. void setTrackedCoarseLocation(const LLVector3d& global_pos);
  66. void agentFound(const LLUUID& prey,
  67. const LLVector3d& estimated_global_pos);
  68. public:
  69. LLUUID mAvatarID;
  70. std::string mName;
  71. LLVector3d mGlobalPositionEstimate;
  72. bool mHaveInfo;
  73. bool mHaveCoarseInfo;
  74. LLTimer mCoarseLocationTimer;
  75. LLTimer mUpdateTimer;
  76. LLTimer mAgentGone;
  77. };
  78. const F32 COARSE_FREQUENCY = 2.2f;
  79. const F32 FIND_FREQUENCY = 29.7f; // This results in a database query, so cut these back
  80. const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;
  81. // static
  82. LLAvatarTracker LLAvatarTracker::sInstance;
  83. static void on_avatar_name_cache_notify(const LLUUID& agent_id,
  84. const LLAvatarName& av_name,
  85. bool online,
  86. LLSD payload);
  87. ///----------------------------------------------------------------------------
  88. /// Class LLAvatarTracker
  89. ///----------------------------------------------------------------------------
  90. LLAvatarTracker::LLAvatarTracker() :
  91. mTrackingData(NULL),
  92. mTrackedAgentValid(false),
  93. //mInventory(NULL),
  94. //mInventoryObserver(NULL),
  95. mModifyMask(0x0)
  96. {
  97. }
  98. LLAvatarTracker::~LLAvatarTracker()
  99. {
  100. deleteTrackingData();
  101. std::for_each(mObservers.begin(), mObservers.end(), DeletePointer());
  102. std::for_each(mBuddyInfo.begin(), mBuddyInfo.end(), DeletePairedPointer());
  103. }
  104. void LLAvatarTracker::track(const LLUUID& avatar_id, const std::string& name)
  105. {
  106. deleteTrackingData();
  107. mTrackedAgentValid = false;
  108. mTrackingData = new LLTrackingData(avatar_id, name);
  109. findAgent();
  110. // We track here because findAgent() is called on a timer (for now).
  111. if(avatar_id.notNull())
  112. {
  113. LLMessageSystem* msg = gMessageSystem;
  114. msg->newMessageFast(_PREHASH_TrackAgent);
  115. msg->nextBlockFast(_PREHASH_AgentData);
  116. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  117. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  118. msg->nextBlockFast(_PREHASH_TargetData);
  119. msg->addUUIDFast(_PREHASH_PreyID, avatar_id);
  120. gAgent.sendReliableMessage();
  121. }
  122. }
  123. void LLAvatarTracker::untrack(const LLUUID& avatar_id)
  124. {
  125. if (mTrackingData && mTrackingData->mAvatarID == avatar_id)
  126. {
  127. deleteTrackingData();
  128. mTrackedAgentValid = false;
  129. LLMessageSystem* msg = gMessageSystem;
  130. msg->newMessageFast(_PREHASH_TrackAgent);
  131. msg->nextBlockFast(_PREHASH_AgentData);
  132. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  133. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  134. msg->nextBlockFast(_PREHASH_TargetData);
  135. msg->addUUIDFast(_PREHASH_PreyID, LLUUID::null);
  136. gAgent.sendReliableMessage();
  137. }
  138. }
  139. void LLAvatarTracker::setTrackedCoarseLocation(const LLVector3d& global_pos)
  140. {
  141. if(mTrackingData)
  142. {
  143. mTrackingData->setTrackedCoarseLocation(global_pos);
  144. }
  145. }
  146. bool LLAvatarTracker::haveTrackingInfo()
  147. {
  148. if(mTrackingData)
  149. {
  150. return mTrackingData->haveTrackingInfo();
  151. }
  152. return false;
  153. }
  154. LLVector3d LLAvatarTracker::getGlobalPos()
  155. {
  156. if(!mTrackedAgentValid || !mTrackingData) return LLVector3d();
  157. LLVector3d global_pos;
  158. LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID);
  159. if(object && !object->isDead())
  160. {
  161. global_pos = object->getPositionGlobal();
  162. // HACK - for making the tracker point above the avatar's head
  163. // rather than its groin
  164. global_pos.mdV[VZ] += 0.7f * ((LLVOAvatar *)object)->mBodySize.mV[VZ];
  165. mTrackingData->mGlobalPositionEstimate = global_pos;
  166. }
  167. else
  168. {
  169. global_pos = mTrackingData->mGlobalPositionEstimate;
  170. }
  171. return global_pos;
  172. }
  173. void LLAvatarTracker::getDegreesAndDist(F32& rot,
  174. F64& horiz_dist,
  175. F64& vert_dist)
  176. {
  177. if(!mTrackingData) return;
  178. LLVector3d global_pos;
  179. LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID);
  180. if(object && !object->isDead())
  181. {
  182. global_pos = object->getPositionGlobal();
  183. mTrackingData->mGlobalPositionEstimate = global_pos;
  184. }
  185. else
  186. {
  187. global_pos = mTrackingData->mGlobalPositionEstimate;
  188. }
  189. LLVector3d to_vec = global_pos - gAgent.getPositionGlobal();
  190. horiz_dist = sqrt(to_vec.mdV[VX] * to_vec.mdV[VX] + to_vec.mdV[VY] * to_vec.mdV[VY]);
  191. vert_dist = to_vec.mdV[VZ];
  192. rot = F32(RAD_TO_DEG * atan2(to_vec.mdV[VY], to_vec.mdV[VX]));
  193. }
  194. const std::string& LLAvatarTracker::getName()
  195. {
  196. if(mTrackingData)
  197. {
  198. return mTrackingData->mName;
  199. }
  200. else
  201. {
  202. return LLStringUtil::null;
  203. }
  204. }
  205. const LLUUID& LLAvatarTracker::getAvatarID()
  206. {
  207. if(mTrackingData)
  208. {
  209. return mTrackingData->mAvatarID;
  210. }
  211. else
  212. {
  213. return LLUUID::null;
  214. }
  215. }
  216. S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
  217. {
  218. using namespace std;
  219. U32 new_buddy_count = 0;
  220. std::string full_name;
  221. LLUUID agent_id;
  222. for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr)
  223. {
  224. agent_id = (*itr).first;
  225. buddy_map_t::const_iterator existing_buddy = mBuddyInfo.find(agent_id);
  226. if(existing_buddy == mBuddyInfo.end())
  227. {
  228. ++new_buddy_count;
  229. mBuddyInfo[agent_id] = (*itr).second;
  230. // IDEVO: is this necessary? name is unused?
  231. gCacheName->getFullName(agent_id, full_name);
  232. addChangedMask(LLFriendObserver::ADD, agent_id);
  233. lldebugs << "Added buddy " << agent_id
  234. << ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
  235. << ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo()
  236. << ", FROM: " << mBuddyInfo[agent_id]->getRightsGrantedFrom()
  237. << llendl;
  238. }
  239. else
  240. {
  241. LLRelationship* e_r = (*existing_buddy).second;
  242. LLRelationship* n_r = (*itr).second;
  243. llwarns << "!! Add buddy for existing buddy: " << agent_id
  244. << " [" << (e_r->isOnline() ? "Online" : "Offline") << "->" << (n_r->isOnline() ? "Online" : "Offline")
  245. << ", " << e_r->getRightsGrantedTo() << "->" << n_r->getRightsGrantedTo()
  246. << ", " << e_r->getRightsGrantedTo() << "->" << n_r->getRightsGrantedTo()
  247. << "]" << llendl;
  248. }
  249. }
  250. notifyObservers();
  251. return new_buddy_count;
  252. }
  253. void LLAvatarTracker::copyBuddyList(buddy_map_t& buddies) const
  254. {
  255. buddy_map_t::const_iterator it = mBuddyInfo.begin();
  256. buddy_map_t::const_iterator end = mBuddyInfo.end();
  257. for(; it != end; ++it)
  258. {
  259. buddies[(*it).first] = (*it).second;
  260. }
  261. }
  262. void LLAvatarTracker::terminateBuddy(const LLUUID& id)
  263. {
  264. lldebugs << "LLAvatarTracker::terminateBuddy()" << llendl;
  265. LLRelationship* buddy = get_ptr_in_map(mBuddyInfo, id);
  266. if(!buddy) return;
  267. mBuddyInfo.erase(id);
  268. LLMessageSystem* msg = gMessageSystem;
  269. msg->newMessage("TerminateFriendship");
  270. msg->nextBlock("AgentData");
  271. msg->addUUID("AgentID", gAgent.getID());
  272. msg->addUUID("SessionID", gAgent.getSessionID());
  273. msg->nextBlock("ExBlock");
  274. msg->addUUID("OtherID", id);
  275. gAgent.sendReliableMessage();
  276. addChangedMask(LLFriendObserver::REMOVE, id);
  277. delete buddy;
  278. }
  279. // get all buddy info
  280. const LLRelationship* LLAvatarTracker::getBuddyInfo(const LLUUID& id) const
  281. {
  282. if(id.isNull()) return NULL;
  283. return get_ptr_in_map(mBuddyInfo, id);
  284. }
  285. bool LLAvatarTracker::isBuddy(const LLUUID& id) const
  286. {
  287. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  288. return (info != NULL);
  289. }
  290. // online status
  291. void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
  292. {
  293. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  294. if(info)
  295. {
  296. info->online(is_online);
  297. addChangedMask(LLFriendObserver::ONLINE, id);
  298. lldebugs << "Set buddy " << id << (is_online ? " Online" : " Offline") << llendl;
  299. }
  300. else
  301. {
  302. llwarns << "!! No buddy info found for " << id
  303. << ", setting to " << (is_online ? "Online" : "Offline") << llendl;
  304. }
  305. }
  306. bool LLAvatarTracker::isBuddyOnline(const LLUUID& id) const
  307. {
  308. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  309. if(info)
  310. {
  311. return info->isOnline();
  312. }
  313. return false;
  314. }
  315. // empowered status
  316. void LLAvatarTracker::setBuddyEmpowered(const LLUUID& id, bool is_empowered)
  317. {
  318. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  319. if(info)
  320. {
  321. info->grantRights(LLRelationship::GRANT_MODIFY_OBJECTS, 0);
  322. mModifyMask |= LLFriendObserver::POWERS;
  323. }
  324. }
  325. bool LLAvatarTracker::isBuddyEmpowered(const LLUUID& id) const
  326. {
  327. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  328. if(info)
  329. {
  330. return info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
  331. }
  332. return false;
  333. }
  334. void LLAvatarTracker::empower(const LLUUID& id, bool grant)
  335. {
  336. // wrapper for ease of use in some situations.
  337. buddy_map_t list;
  338. /*
  339. list.insert(id);
  340. empowerList(list, grant);
  341. */
  342. }
  343. void LLAvatarTracker::empowerList(const buddy_map_t& list, bool grant)
  344. {
  345. llwarns << "LLAvatarTracker::empowerList() not implemented." << llendl;
  346. /*
  347. LLMessageSystem* msg = gMessageSystem;
  348. const char* message_name;
  349. const char* block_name;
  350. const char* field_name;
  351. if(grant)
  352. {
  353. message_name = _PREHASH_GrantModification;
  354. block_name = _PREHASH_EmpoweredBlock;
  355. field_name = _PREHASH_EmpoweredID;
  356. }
  357. else
  358. {
  359. message_name = _PREHASH_RevokeModification;
  360. block_name = _PREHASH_RevokedBlock;
  361. field_name = _PREHASH_RevokedID;
  362. }
  363. std::string name;
  364. gAgent.buildFullnameAndTitle(name);
  365. bool start_new_message = true;
  366. buddy_list_t::const_iterator it = list.begin();
  367. buddy_list_t::const_iterator end = list.end();
  368. for(; it != end; ++it)
  369. {
  370. if(NULL == get_ptr_in_map(mBuddyInfo, (*it))) continue;
  371. setBuddyEmpowered((*it), grant);
  372. if(start_new_message)
  373. {
  374. start_new_message = false;
  375. msg->newMessageFast(message_name);
  376. msg->nextBlockFast(_PREHASH_AgentData);
  377. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  378. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  379. msg->addStringFast(_PREHASH_GranterName, name);
  380. }
  381. msg->nextBlockFast(block_name);
  382. msg->addUUIDFast(field_name, (*it));
  383. if(msg->isSendFullFast(block_name))
  384. {
  385. start_new_message = true;
  386. gAgent.sendReliableMessage();
  387. }
  388. }
  389. if(!start_new_message)
  390. {
  391. gAgent.sendReliableMessage();
  392. }
  393. */
  394. }
  395. void LLAvatarTracker::deleteTrackingData()
  396. {
  397. //make sure mTrackingData never points to freed memory
  398. LLTrackingData* tmp = mTrackingData;
  399. mTrackingData = NULL;
  400. delete tmp;
  401. }
  402. void LLAvatarTracker::findAgent()
  403. {
  404. if (!mTrackingData) return;
  405. if (mTrackingData->mAvatarID.isNull()) return;
  406. LLMessageSystem* msg = gMessageSystem;
  407. msg->newMessageFast(_PREHASH_FindAgent); // Request
  408. msg->nextBlockFast(_PREHASH_AgentBlock);
  409. msg->addUUIDFast(_PREHASH_Hunter, gAgentID);
  410. msg->addUUIDFast(_PREHASH_Prey, mTrackingData->mAvatarID);
  411. msg->addU32Fast(_PREHASH_SpaceIP, 0); // will get filled in by simulator
  412. msg->nextBlockFast(_PREHASH_LocationBlock);
  413. const F64 NO_LOCATION = 0.0;
  414. msg->addF64Fast(_PREHASH_GlobalX, NO_LOCATION);
  415. msg->addF64Fast(_PREHASH_GlobalY, NO_LOCATION);
  416. gAgent.sendReliableMessage();
  417. }
  418. void LLAvatarTracker::addObserver(LLFriendObserver* observer)
  419. {
  420. if(observer)
  421. {
  422. mObservers.push_back(observer);
  423. }
  424. }
  425. void LLAvatarTracker::removeObserver(LLFriendObserver* observer)
  426. {
  427. mObservers.erase(
  428. std::remove(mObservers.begin(), mObservers.end(), observer),
  429. mObservers.end());
  430. }
  431. void LLAvatarTracker::notifyObservers()
  432. {
  433. observer_list_t observers(mObservers);
  434. observer_list_t::iterator it = observers.begin();
  435. observer_list_t::iterator end = observers.end();
  436. for(; it != end; ++it)
  437. {
  438. (*it)->changed(mModifyMask);
  439. }
  440. for (changed_buddy_t::iterator it = mChangedBuddyIDs.begin(); it != mChangedBuddyIDs.end(); it++)
  441. {
  442. notifyParticularFriendObservers(*it);
  443. }
  444. mModifyMask = LLFriendObserver::NONE;
  445. mChangedBuddyIDs.clear();
  446. }
  447. void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
  448. {
  449. if (buddy_id.notNull() && observer)
  450. mParticularFriendObserverMap[buddy_id].insert(observer);
  451. }
  452. void LLAvatarTracker::removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
  453. {
  454. if (buddy_id.isNull() || !observer)
  455. return;
  456. observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
  457. if(obs_it == mParticularFriendObserverMap.end())
  458. return;
  459. obs_it->second.erase(observer);
  460. // purge empty sets from the map
  461. if (obs_it->second.size() == 0)
  462. mParticularFriendObserverMap.erase(obs_it);
  463. }
  464. void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id)
  465. {
  466. observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
  467. if(obs_it == mParticularFriendObserverMap.end())
  468. return;
  469. // Notify observers interested in buddy_id.
  470. observer_set_t& obs = obs_it->second;
  471. for (observer_set_t::iterator ob_it = obs.begin(); ob_it != obs.end(); ob_it++)
  472. {
  473. (*ob_it)->changed(mModifyMask);
  474. }
  475. }
  476. // store flag for change
  477. // and id of object change applies to
  478. void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent)
  479. {
  480. mModifyMask |= mask;
  481. if (referent.notNull())
  482. {
  483. mChangedBuddyIDs.insert(referent);
  484. }
  485. }
  486. void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f)
  487. {
  488. buddy_map_t::iterator it = mBuddyInfo.begin();
  489. buddy_map_t::iterator end = mBuddyInfo.end();
  490. for(; it != end; ++it)
  491. {
  492. f((*it).first, (*it).second);
  493. }
  494. }
  495. void LLAvatarTracker::registerCallbacks(LLMessageSystem* msg)
  496. {
  497. msg->setHandlerFuncFast(_PREHASH_FindAgent, processAgentFound);
  498. msg->setHandlerFuncFast(_PREHASH_OnlineNotification,
  499. processOnlineNotification);
  500. msg->setHandlerFuncFast(_PREHASH_OfflineNotification,
  501. processOfflineNotification);
  502. //msg->setHandlerFuncFast(_PREHASH_GrantedProxies,
  503. // processGrantedProxies);
  504. msg->setHandlerFunc("TerminateFriendship", processTerminateFriendship);
  505. msg->setHandlerFunc(_PREHASH_ChangeUserRights, processChangeUserRights);
  506. }
  507. // static
  508. void LLAvatarTracker::processAgentFound(LLMessageSystem* msg, void**)
  509. {
  510. LLUUID id;
  511. msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Hunter, id);
  512. msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Prey, id);
  513. // *FIX: should make sure prey id matches.
  514. LLVector3d estimated_global_pos;
  515. msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalX,
  516. estimated_global_pos.mdV[VX]);
  517. msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalY,
  518. estimated_global_pos.mdV[VY]);
  519. LLAvatarTracker::instance().agentFound(id, estimated_global_pos);
  520. }
  521. void LLAvatarTracker::agentFound(const LLUUID& prey,
  522. const LLVector3d& estimated_global_pos)
  523. {
  524. if(!mTrackingData) return;
  525. //if we get a valid reply from the server, that means the agent
  526. //is our friend and mappable, so enable interest list based updates
  527. LLAvatarTracker::instance().setTrackedAgentValid(true);
  528. mTrackingData->agentFound(prey, estimated_global_pos);
  529. }
  530. // static
  531. void LLAvatarTracker::processOnlineNotification(LLMessageSystem* msg, void**)
  532. {
  533. lldebugs << "LLAvatarTracker::processOnlineNotification()" << llendl;
  534. instance().processNotify(msg, true);
  535. }
  536. // static
  537. void LLAvatarTracker::processOfflineNotification(LLMessageSystem* msg, void**)
  538. {
  539. lldebugs << "LLAvatarTracker::processOfflineNotification()" << llendl;
  540. instance().processNotify(msg, false);
  541. }
  542. void LLAvatarTracker::processChange(LLMessageSystem* msg)
  543. {
  544. S32 count = msg->getNumberOfBlocksFast(_PREHASH_Rights);
  545. LLUUID agent_id, agent_related;
  546. S32 new_rights;
  547. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
  548. for(int i = 0; i < count; ++i)
  549. {
  550. msg->getUUIDFast(_PREHASH_Rights, _PREHASH_AgentRelated, agent_related, i);
  551. msg->getS32Fast(_PREHASH_Rights,_PREHASH_RelatedRights, new_rights, i);
  552. if(agent_id == gAgent.getID())
  553. {
  554. if(mBuddyInfo.find(agent_related) != mBuddyInfo.end())
  555. {
  556. (mBuddyInfo[agent_related])->setRightsTo(new_rights);
  557. }
  558. }
  559. else
  560. {
  561. if(mBuddyInfo.find(agent_id) != mBuddyInfo.end())
  562. {
  563. if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
  564. {
  565. LLSD args;
  566. args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString();
  567. LLSD payload;
  568. payload["from_id"] = agent_id;
  569. if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
  570. {
  571. LLNotificationsUtil::add("GrantedModifyRights",args, payload);
  572. }
  573. else
  574. {
  575. LLNotificationsUtil::add("RevokedModifyRights",args, payload);
  576. }
  577. }
  578. (mBuddyInfo[agent_id])->setRightsFrom(new_rights);
  579. }
  580. }
  581. }
  582. addChangedMask(LLFriendObserver::POWERS, agent_id);
  583. notifyObservers();
  584. }
  585. void LLAvatarTracker::processChangeUserRights(LLMessageSystem* msg, void**)
  586. {
  587. lldebugs << "LLAvatarTracker::processChangeUserRights()" << llendl;
  588. instance().processChange(msg);
  589. }
  590. void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
  591. {
  592. S32 count = msg->getNumberOfBlocksFast(_PREHASH_AgentBlock);
  593. BOOL chat_notify = gSavedSettings.getBOOL("ChatOnlineNotification");
  594. lldebugs << "Received " << count << " online notifications **** " << llendl;
  595. if(count > 0)
  596. {
  597. LLUUID agent_id;
  598. const LLRelationship* info = NULL;
  599. LLUUID tracking_id;
  600. if(mTrackingData)
  601. {
  602. tracking_id = mTrackingData->mAvatarID;
  603. }
  604. LLSD payload;
  605. for(S32 i = 0; i < count; ++i)
  606. {
  607. msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_AgentID, agent_id, i);
  608. payload["FROM_ID"] = agent_id;
  609. info = getBuddyInfo(agent_id);
  610. if(info)
  611. {
  612. setBuddyOnline(agent_id,online);
  613. }
  614. else
  615. {
  616. llwarns << "Received online notification for unknown buddy: "
  617. << agent_id << " is " << (online ? "ONLINE" : "OFFLINE") << llendl;
  618. }
  619. if(tracking_id == agent_id)
  620. {
  621. // we were tracking someone who went offline
  622. deleteTrackingData();
  623. }
  624. // *TODO: get actual inventory id
  625. gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD, LLUUID::null);
  626. }
  627. if(chat_notify)
  628. {
  629. // Look up the name of this agent for the notification
  630. LLAvatarNameCache::get(agent_id,
  631. boost::bind(&on_avatar_name_cache_notify,
  632. _1, _2, online, payload));
  633. }
  634. mModifyMask |= LLFriendObserver::ONLINE;
  635. instance().notifyObservers();
  636. gInventory.notifyObservers();
  637. }
  638. }
  639. static void on_avatar_name_cache_notify(const LLUUID& agent_id,
  640. const LLAvatarName& av_name,
  641. bool online,
  642. LLSD payload)
  643. {
  644. // Popup a notify box with online status of this agent
  645. // Use display name only because this user is your friend
  646. LLSD args;
  647. args["NAME"] = av_name.mDisplayName;
  648. LLNotificationPtr notification;
  649. if (online)
  650. {
  651. notification =
  652. LLNotificationsUtil::add("FriendOnline",
  653. args,
  654. payload.with("respond_on_mousedown", TRUE),
  655. boost::bind(&LLAvatarActions::startIM, agent_id));
  656. }
  657. else
  658. {
  659. notification =
  660. LLNotificationsUtil::add("FriendOffline", args, payload);
  661. }
  662. // If there's an open IM session with this agent, send a notification there too.
  663. LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
  664. std::string notify_msg = notification->getMessage();
  665. LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
  666. }
  667. void LLAvatarTracker::formFriendship(const LLUUID& id)
  668. {
  669. if(id.notNull())
  670. {
  671. LLRelationship* buddy_info = get_ptr_in_map(instance().mBuddyInfo, id);
  672. if(!buddy_info)
  673. {
  674. LLAvatarTracker& at = LLAvatarTracker::instance();
  675. //The default for relationship establishment is to have both parties
  676. //visible online to each other.
  677. buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,LLRelationship::GRANT_ONLINE_STATUS, false);
  678. at.mBuddyInfo[id] = buddy_info;
  679. at.addChangedMask(LLFriendObserver::ADD, id);
  680. at.notifyObservers();
  681. }
  682. }
  683. }
  684. void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**)
  685. {
  686. LLUUID id;
  687. msg->getUUID("ExBlock", "OtherID", id);
  688. if(id.notNull())
  689. {
  690. LLAvatarTracker& at = LLAvatarTracker::instance();
  691. LLRelationship* buddy = get_ptr_in_map(at.mBuddyInfo, id);
  692. if(!buddy) return;
  693. at.mBuddyInfo.erase(id);
  694. at.addChangedMask(LLFriendObserver::REMOVE, id);
  695. delete buddy;
  696. at.notifyObservers();
  697. }
  698. }
  699. ///----------------------------------------------------------------------------
  700. /// Tracking Data
  701. ///----------------------------------------------------------------------------
  702. LLTrackingData::LLTrackingData(const LLUUID& avatar_id, const std::string& name)
  703. : mAvatarID(avatar_id),
  704. mHaveInfo(false),
  705. mHaveCoarseInfo(false)
  706. {
  707. mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY);
  708. mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
  709. mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
  710. if(!name.empty())
  711. {
  712. mName = name;
  713. }
  714. }
  715. void LLTrackingData::agentFound(const LLUUID& prey,
  716. const LLVector3d& estimated_global_pos)
  717. {
  718. if(prey != mAvatarID)
  719. {
  720. llwarns << "LLTrackingData::agentFound() - found " << prey
  721. << " but looking for " << mAvatarID << llendl;
  722. }
  723. mHaveInfo = true;
  724. mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
  725. mGlobalPositionEstimate = estimated_global_pos;
  726. }
  727. bool LLTrackingData::haveTrackingInfo()
  728. {
  729. LLViewerObject* object = gObjectList.findObject(mAvatarID);
  730. if(object && !object->isDead())
  731. {
  732. mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY);
  733. mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
  734. mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
  735. mHaveInfo = true;
  736. return true;
  737. }
  738. if(mHaveCoarseInfo &&
  739. !mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY))
  740. {
  741. // if we reach here, then we have a 'recent' coarse update
  742. mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
  743. mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
  744. return true;
  745. }
  746. if(mUpdateTimer.checkExpirationAndReset(FIND_FREQUENCY))
  747. {
  748. LLAvatarTracker::instance().findAgent();
  749. mHaveCoarseInfo = false;
  750. }
  751. if(mAgentGone.checkExpirationAndReset(OFFLINE_SECONDS))
  752. {
  753. mHaveInfo = false;
  754. mHaveCoarseInfo = false;
  755. }
  756. return mHaveInfo;
  757. }
  758. void LLTrackingData::setTrackedCoarseLocation(const LLVector3d& global_pos)
  759. {
  760. mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY);
  761. mGlobalPositionEstimate = global_pos;
  762. mHaveInfo = true;
  763. mHaveCoarseInfo = true;
  764. }
  765. ///----------------------------------------------------------------------------
  766. // various buddy functors
  767. ///----------------------------------------------------------------------------
  768. bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
  769. {
  770. if(buddy->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS))
  771. {
  772. mProxy.insert(buddy_id);
  773. }
  774. return true;
  775. }
  776. bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
  777. {
  778. LLAvatarName av_name;
  779. LLAvatarNameCache::get( buddy_id, &av_name);
  780. buddy_map_t::value_type value(av_name.mDisplayName, buddy_id);
  781. if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION))
  782. {
  783. mMappable.insert(value);
  784. }
  785. return true;
  786. }
  787. bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
  788. {
  789. gCacheName->getFullName(buddy_id, mFullName);
  790. buddy_map_t::value_type value(mFullName, buddy_id);
  791. if(buddy->isOnline())
  792. {
  793. mOnline.insert(value);
  794. }
  795. return true;
  796. }
  797. bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
  798. {
  799. LLAvatarName av_name;
  800. LLAvatarNameCache::get(buddy_id, &av_name);
  801. mFullName = av_name.mDisplayName;
  802. buddy_map_t::value_type value(mFullName, buddy_id);
  803. if(buddy->isOnline())
  804. {
  805. mOnline.insert(value);
  806. }
  807. else
  808. {
  809. mOffline.insert(value);
  810. }
  811. return true;
  812. }