llavatartracker.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. /**
  2. * @file llavatartracker.cpp
  3. * @brief Implementation of the LLAvatarTracker and associated classes
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #if LL_WINDOWS
  34. # pragma warning(disable : 4800) // Performance warning in <functional>
  35. #endif
  36. #include "llavatartracker.h"
  37. #include "llbutton.h"
  38. #include "llcachename.h"
  39. #include "llnotifications.h"
  40. #include "llmessage.h"
  41. #include "llagent.h"
  42. #include "llfloaterim.h"
  43. #include "llimmgr.h"
  44. #include "llinventorymodel.h"
  45. #include "llgridmanager.h"
  46. #include "llviewercontrol.h"
  47. #include "llviewerobjectlist.h"
  48. #include "llvoavatar.h"
  49. ///----------------------------------------------------------------------------
  50. /// Local function declarations, constants, enums, and typedefs
  51. ///----------------------------------------------------------------------------
  52. class LLTrackingData
  53. {
  54. public:
  55. LLTrackingData(const LLUUID& avatar_id, const std::string& name);
  56. bool haveTrackingInfo();
  57. void setTrackedCoarseLocation(const LLVector3d& global_pos);
  58. void agentFound(const LLUUID& prey,
  59. const LLVector3d& estimated_global_pos);
  60. public:
  61. LLUUID mAvatarID;
  62. std::string mName;
  63. LLVector3d mGlobalPositionEstimate;
  64. LLTimer mCoarseLocationTimer;
  65. LLTimer mUpdateTimer;
  66. LLTimer mAgentGone;
  67. bool mHaveInfo;
  68. bool mHaveCoarseInfo;
  69. };
  70. constexpr F32 COARSE_FREQUENCY = 2.2f;
  71. // This results in a database query, so cut these back:
  72. constexpr F32 FIND_FREQUENCY = 29.7f;
  73. constexpr F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.f;
  74. LLAvatarTracker gAvatarTracker;
  75. ///----------------------------------------------------------------------------
  76. /// Class LLAvatarTracker
  77. ///----------------------------------------------------------------------------
  78. LLAvatarTracker::LLAvatarTracker()
  79. : mTrackingData(NULL),
  80. mTrackedAgentValid(false),
  81. mModifyMask(0x0),
  82. mIsNotifyObservers(false)
  83. {
  84. }
  85. LLAvatarTracker::~LLAvatarTracker()
  86. {
  87. deleteTrackingData();
  88. std::for_each(mObservers.begin(), mObservers.end(), DeletePointer());
  89. mObservers.clear();
  90. for (auto it = mBuddyInfo.begin(), end = mBuddyInfo.end(); it != end; ++it)
  91. {
  92. delete it->second;
  93. }
  94. mBuddyInfo.clear();
  95. }
  96. void LLAvatarTracker::track(const LLUUID& avatar_id, const std::string& name)
  97. {
  98. deleteTrackingData();
  99. mTrackedAgentValid = false;
  100. mTrackingData = new LLTrackingData(avatar_id, name);
  101. findAgent();
  102. // We track here because findAgent() is called on a timer (for now).
  103. if (avatar_id.notNull())
  104. {
  105. LLMessageSystem* msg = gMessageSystemp;
  106. msg->newMessageFast(_PREHASH_TrackAgent);
  107. msg->nextBlockFast(_PREHASH_AgentData);
  108. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  109. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  110. msg->nextBlockFast(_PREHASH_TargetData);
  111. msg->addUUIDFast(_PREHASH_PreyID, avatar_id);
  112. gAgent.sendReliableMessage();
  113. }
  114. }
  115. void LLAvatarTracker::untrack(const LLUUID& avatar_id)
  116. {
  117. if (mTrackingData && mTrackingData->mAvatarID == avatar_id)
  118. {
  119. deleteTrackingData();
  120. mTrackedAgentValid = false;
  121. LLMessageSystem* msg = gMessageSystemp;
  122. msg->newMessageFast(_PREHASH_TrackAgent);
  123. msg->nextBlockFast(_PREHASH_AgentData);
  124. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  125. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  126. msg->nextBlockFast(_PREHASH_TargetData);
  127. msg->addUUIDFast(_PREHASH_PreyID, LLUUID::null);
  128. gAgent.sendReliableMessage();
  129. }
  130. }
  131. void LLAvatarTracker::setTrackedCoarseLocation(const LLVector3d& global_pos)
  132. {
  133. if (mTrackingData)
  134. {
  135. mTrackingData->setTrackedCoarseLocation(global_pos);
  136. }
  137. }
  138. bool LLAvatarTracker::haveTrackingInfo()
  139. {
  140. if (mTrackingData)
  141. {
  142. return mTrackingData->haveTrackingInfo();
  143. }
  144. return false;
  145. }
  146. LLVector3d LLAvatarTracker::getGlobalPos()
  147. {
  148. if (!mTrackedAgentValid || !mTrackingData) return LLVector3d();
  149. LLVector3d global_pos;
  150. LLVOAvatar* avatarp = gObjectList.findAvatar(mTrackingData->mAvatarID);
  151. if (avatarp && !avatarp->isDead())
  152. {
  153. global_pos = avatarp->getPositionGlobal();
  154. // *HACK: for making the tracker point above the avatar's head rather
  155. // than to its groin
  156. global_pos.mdV[VZ] += 0.7f * (avatarp->mBodySize.mV[VZ] +
  157. avatarp->mAvatarOffset.mV[VZ]);
  158. mTrackingData->mGlobalPositionEstimate = global_pos;
  159. }
  160. else
  161. {
  162. global_pos = mTrackingData->mGlobalPositionEstimate;
  163. }
  164. return global_pos;
  165. }
  166. void LLAvatarTracker::getDegreesAndDist(F32& rot, F64& horiz_dist,
  167. F64& vert_dist)
  168. {
  169. if (!mTrackingData) return;
  170. LLVector3d global_pos;
  171. LLVOAvatar* avatarp = gObjectList.findAvatar(mTrackingData->mAvatarID);
  172. if (avatarp && !avatarp->isDead())
  173. {
  174. global_pos = avatarp->getPositionGlobal();
  175. mTrackingData->mGlobalPositionEstimate = global_pos;
  176. }
  177. else
  178. {
  179. global_pos = mTrackingData->mGlobalPositionEstimate;
  180. }
  181. LLVector3d to_vec = global_pos - gAgent.getPositionGlobal();
  182. horiz_dist = sqrtf(to_vec.mdV[VX] * to_vec.mdV[VX] +
  183. to_vec.mdV[VY] * to_vec.mdV[VY]);
  184. vert_dist = to_vec.mdV[VZ];
  185. rot = RAD_TO_DEG * atan2f(to_vec.mdV[VY], to_vec.mdV[VX]);
  186. }
  187. const std::string& LLAvatarTracker::getName()
  188. {
  189. return mTrackingData ? mTrackingData->mName : LLStringUtil::null;
  190. }
  191. const LLUUID& LLAvatarTracker::getAvatarID()
  192. {
  193. return mTrackingData ? mTrackingData->mAvatarID : LLUUID::null;
  194. }
  195. S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
  196. {
  197. U32 new_buddy_count = 0;
  198. std::string first, last;
  199. LLUUID agent_id;
  200. for (buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end();
  201. ++itr)
  202. {
  203. agent_id = itr->first;
  204. buddy_map_t::const_iterator existing_buddy = mBuddyInfo.find(agent_id);
  205. if (existing_buddy == mBuddyInfo.end())
  206. {
  207. ++new_buddy_count;
  208. mBuddyInfo[agent_id] = itr->second;
  209. if (gCacheNamep)
  210. {
  211. gCacheNamep->getName(agent_id, first, last);
  212. }
  213. addChangedMask(LLFriendObserver::ADD, agent_id);
  214. LL_DEBUGS("AvatarTracker") << "Added buddy " << agent_id << ", "
  215. << (mBuddyInfo[agent_id]->isOnline() ? "Online"
  216. : "Offline")
  217. << ", TO: "
  218. << mBuddyInfo[agent_id]->getRightsGrantedTo()
  219. << ", FROM: "
  220. << mBuddyInfo[agent_id]->getRightsGrantedFrom()
  221. << LL_ENDL;
  222. }
  223. else
  224. {
  225. LLRelationship* e_r = existing_buddy->second;
  226. LLRelationship* n_r = itr->second;
  227. llwarns << "Add buddy for existing buddy: " << agent_id
  228. << " [" << (e_r->isOnline() ? "Online" : "Offline")
  229. << "->" << (n_r->isOnline() ? "Online" : "Offline")
  230. << ", " << e_r->getRightsGrantedTo()
  231. << "->" << n_r->getRightsGrantedTo()
  232. << ", " << e_r->getRightsGrantedTo()
  233. << "->" << n_r->getRightsGrantedTo() << "]" << llendl;
  234. }
  235. }
  236. // Do not notify observers here: list can be large so let it be done on
  237. // idle instead (via a call to gAvatarTracker.idleNotifyObservers() in
  238. // llappviewer.cpp)
  239. return new_buddy_count;
  240. }
  241. void LLAvatarTracker::copyBuddyList(buddy_map_t& buddies) const
  242. {
  243. for (buddy_map_t::const_iterator it = mBuddyInfo.begin(),
  244. end = mBuddyInfo.end();
  245. it != end; ++it)
  246. {
  247. buddies[it->first] = it->second;
  248. }
  249. }
  250. void LLAvatarTracker::terminateBuddy(const LLUUID& id)
  251. {
  252. LL_DEBUGS("AvatarTracker") << "Terminating friendship with avatar Id: "
  253. << id << LL_ENDL;
  254. LLRelationship* buddy = get_ptr_in_map(mBuddyInfo, id);
  255. if (buddy)
  256. {
  257. mBuddyInfo.erase(id);
  258. LLMessageSystem* msg = gMessageSystemp;
  259. msg->newMessage(_PREHASH_TerminateFriendship);
  260. msg->nextBlock(_PREHASH_AgentData);
  261. msg->addUUID(_PREHASH_AgentID, gAgentID);
  262. msg->addUUID(_PREHASH_SessionID, gAgentSessionID);
  263. msg->nextBlock(_PREHASH_ExBlock);
  264. msg->addUUID(_PREHASH_OtherID, id);
  265. gAgent.sendReliableMessage();
  266. addChangedMask(LLFriendObserver::REMOVE, id);
  267. delete buddy;
  268. LLVOAvatar* avatarp = gObjectList.findAvatar(id);
  269. if (avatarp)
  270. {
  271. static LLCachedControl<LLColor4U> map_avatar(gColors, "MapAvatar");
  272. avatarp->setMinimapColor(LLColor4(map_avatar));
  273. }
  274. }
  275. }
  276. // Get all buddy info
  277. const LLRelationship* LLAvatarTracker::getBuddyInfo(const LLUUID& id) const
  278. {
  279. if (id.isNull())
  280. {
  281. return NULL;
  282. }
  283. return get_ptr_in_map(mBuddyInfo, id);
  284. }
  285. // Online status
  286. void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
  287. {
  288. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  289. if (!info)
  290. {
  291. llwarns << "No buddy info found for " << id << ", setting to "
  292. << (is_online ? "online" : "offline") << llendl;
  293. return;
  294. }
  295. info->online(is_online);
  296. addChangedMask(LLFriendObserver::ONLINE, id);
  297. LL_DEBUGS("AvatarTracker") << "Set buddy " << id
  298. << (is_online ? " online" : " offline")
  299. << LL_ENDL;
  300. }
  301. bool LLAvatarTracker::isBuddyOnline(const LLUUID& id) const
  302. {
  303. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  304. return info && info->isOnline();
  305. }
  306. #if TRACK_POWER
  307. // empowered status
  308. void LLAvatarTracker::setBuddyEmpowered(const LLUUID& id, bool is_empowered)
  309. {
  310. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  311. if (info)
  312. {
  313. info->grantRights(LLRelationship::GRANT_MODIFY_OBJECTS, 0);
  314. addChangedMask(LLFriendObserver::POWERS, id);
  315. }
  316. }
  317. bool LLAvatarTracker::isBuddyEmpowered(const LLUUID& id) const
  318. {
  319. LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
  320. if (info)
  321. {
  322. return info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
  323. }
  324. return false;
  325. }
  326. // Wrapper for ease of use in some situations.
  327. void LLAvatarTracker::empower(const LLUUID& id, bool grant)
  328. {
  329. buddy_map_t list;
  330. list.insert(id);
  331. empowerList(list, grant);
  332. }
  333. void LLAvatarTracker::empowerList(const buddy_map_t& list, bool grant)
  334. {
  335. const char* message_name;
  336. const char* block_name;
  337. const char* field_name;
  338. if (grant)
  339. {
  340. message_name = _PREHASH_GrantModification;
  341. block_name = _PREHASH_EmpoweredBlock;
  342. field_name = _PREHASH_EmpoweredID;
  343. }
  344. else
  345. {
  346. message_name = _PREHASH_RevokeModification;
  347. block_name = _PREHASH_RevokedBlock;
  348. field_name = _PREHASH_RevokedID;
  349. }
  350. std::string name;
  351. gAgent.buildFullnameAndTitle(name);
  352. LLMessageSystem* msg = gMessageSystemp;
  353. bool start_new_message = true;
  354. buddy_list_t::const_iterator it = list.begin();
  355. buddy_list_t::const_iterator end = list.end();
  356. for ( ; it != end; ++it)
  357. {
  358. if (!get_ptr_in_map(mBuddyInfo, *it)) continue;
  359. setBuddyEmpowered((*it), grant);
  360. if (start_new_message)
  361. {
  362. start_new_message = false;
  363. msg->newMessageFast(message_name);
  364. msg->nextBlockFast(_PREHASH_AgentData);
  365. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  366. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  367. msg->addStringFast(_PREHASH_GranterName, name);
  368. }
  369. msg->nextBlockFast(block_name);
  370. msg->addUUIDFast(field_name, (*it));
  371. if (msg->isSendFullFast(block_name))
  372. {
  373. start_new_message = true;
  374. gAgent.sendReliableMessage();
  375. }
  376. }
  377. if (!start_new_message)
  378. {
  379. gAgent.sendReliableMessage();
  380. }
  381. }
  382. #endif
  383. void LLAvatarTracker::deleteTrackingData()
  384. {
  385. if (mTrackingData)
  386. {
  387. delete mTrackingData;
  388. // Make sure mTrackingData never points to freed memory
  389. mTrackingData = NULL;
  390. }
  391. }
  392. void LLAvatarTracker::findAgent()
  393. {
  394. LLMessageSystem* msg = gMessageSystemp;
  395. if (!msg || !mTrackingData || mTrackingData->mAvatarID.isNull())
  396. {
  397. return;
  398. }
  399. msg->newMessageFast(_PREHASH_FindAgent); // Request
  400. msg->nextBlockFast(_PREHASH_AgentBlock);
  401. msg->addUUIDFast(_PREHASH_Hunter, gAgentID);
  402. msg->addUUIDFast(_PREHASH_Prey, mTrackingData->mAvatarID);
  403. msg->addIPAddrFast(_PREHASH_SpaceIP, 0); // Will get filled in by simulator
  404. msg->nextBlockFast(_PREHASH_LocationBlock);
  405. constexpr F64 NO_LOCATION = 0.0;
  406. msg->addF64Fast(_PREHASH_GlobalX, NO_LOCATION);
  407. msg->addF64Fast(_PREHASH_GlobalY, NO_LOCATION);
  408. gAgent.sendReliableMessage();
  409. }
  410. void LLAvatarTracker::addObserver(LLFriendObserver* observer)
  411. {
  412. if (observer)
  413. {
  414. mObservers.push_back(observer);
  415. }
  416. }
  417. void LLAvatarTracker::removeObserver(LLFriendObserver* observer)
  418. {
  419. mObservers.erase(std::remove(mObservers.begin(), mObservers.end(),
  420. observer),
  421. mObservers.end());
  422. }
  423. void LLAvatarTracker::idleNotifyObservers()
  424. {
  425. if (mModifyMask != LLFriendObserver::NONE)
  426. {
  427. notifyObservers();
  428. }
  429. }
  430. void LLAvatarTracker::notifyObservers()
  431. {
  432. if (mIsNotifyObservers)
  433. {
  434. // Do not allow recursive calls; new masks and Ids will be processed
  435. // later from idle.
  436. return;
  437. }
  438. mIsNotifyObservers = true;
  439. LL_DEBUGS("Friends") << "Notifying observers with mask=" << mModifyMask
  440. << LL_ENDL;
  441. // Copy the list, in case an observer would remove itself on changed event
  442. observer_list_t observers(mObservers);
  443. for (observer_list_t::iterator it = observers.begin(),
  444. end = observers.end();
  445. it != end; ++it)
  446. {
  447. LLFriendObserver* observer = *it;
  448. if (observer)
  449. {
  450. observer->changed(mModifyMask);
  451. observer->changedBuddies(mChangedBuddyIDs);
  452. }
  453. }
  454. mModifyMask = LLFriendObserver::NONE;
  455. mChangedBuddyIDs.clear();
  456. mIsNotifyObservers = false;
  457. }
  458. void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& buddy_id)
  459. {
  460. mModifyMask |= mask;
  461. if (buddy_id.notNull())
  462. {
  463. mChangedBuddyIDs.emplace(buddy_id);
  464. }
  465. }
  466. void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f)
  467. {
  468. for (buddy_map_t::iterator it = mBuddyInfo.begin(), end = mBuddyInfo.end();
  469. it != end; ++it)
  470. {
  471. f(it->first, it->second);
  472. }
  473. }
  474. void LLAvatarTracker::registerCallbacks(LLMessageSystem* msg)
  475. {
  476. msg->setHandlerFuncFast(_PREHASH_FindAgent, processAgentFound);
  477. msg->setHandlerFuncFast(_PREHASH_OnlineNotification,
  478. processOnlineNotification);
  479. msg->setHandlerFuncFast(_PREHASH_OfflineNotification,
  480. processOfflineNotification);
  481. msg->setHandlerFunc(_PREHASH_TerminateFriendship,
  482. processTerminateFriendship);
  483. msg->setHandlerFunc(_PREHASH_ChangeUserRights, processChangeUserRights);
  484. }
  485. //static
  486. void LLAvatarTracker::processAgentFound(LLMessageSystem* msg, void**)
  487. {
  488. LLUUID id;
  489. msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Hunter, id);
  490. msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Prey, id);
  491. // *FIX: should make sure prey id matches.
  492. LLVector3d estimated_global_pos;
  493. msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalX,
  494. estimated_global_pos.mdV[VX]);
  495. msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalY,
  496. estimated_global_pos.mdV[VY]);
  497. gAvatarTracker.agentFound(id, estimated_global_pos);
  498. }
  499. void LLAvatarTracker::agentFound(const LLUUID& prey,
  500. const LLVector3d& estimated_global_pos)
  501. {
  502. // If we get a valid reply from the server, that means the agent is our
  503. // friend and mappable, so enable interest list based updates
  504. if (mTrackingData)
  505. {
  506. gAvatarTracker.setTrackedAgentValid(true);
  507. mTrackingData->agentFound(prey, estimated_global_pos);
  508. }
  509. }
  510. //static
  511. void LLAvatarTracker::processOnlineNotification(LLMessageSystem* msg, void**)
  512. {
  513. LL_DEBUGS("AvatarTracker") << "called" << LL_ENDL;
  514. gAvatarTracker.processNotify(msg, true);
  515. }
  516. //static
  517. void LLAvatarTracker::processOfflineNotification(LLMessageSystem* msg, void**)
  518. {
  519. LL_DEBUGS("AvatarTracker") << "called" << LL_ENDL;
  520. gAvatarTracker.processNotify(msg, false);
  521. }
  522. void LLAvatarTracker::processChange(LLMessageSystem* msg)
  523. {
  524. S32 count = msg->getNumberOfBlocksFast(_PREHASH_Rights);
  525. LLUUID agent_id, agent_related;
  526. S32 new_rights;
  527. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
  528. for (S32 i = 0; i < count; ++i)
  529. {
  530. msg->getUUIDFast(_PREHASH_Rights, _PREHASH_AgentRelated, agent_related,
  531. i);
  532. msg->getS32Fast(_PREHASH_Rights,_PREHASH_RelatedRights, new_rights, i);
  533. if (agent_id == gAgentID)
  534. {
  535. if (mBuddyInfo.find(agent_related) != mBuddyInfo.end())
  536. {
  537. (mBuddyInfo[agent_related])->setRightsTo(new_rights);
  538. }
  539. }
  540. else if (mBuddyInfo.find(agent_id) != mBuddyInfo.end())
  541. {
  542. if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) &
  543. LLRelationship::GRANT_MODIFY_OBJECTS) && !gAgent.getBusy())
  544. {
  545. std::string name;
  546. LLSD args;
  547. if (gCacheNamep && gCacheNamep->getFullName(agent_id, name))
  548. {
  549. if (!LLAvatarName::sLegacyNamesForFriends &&
  550. LLAvatarNameCache::useDisplayNames())
  551. {
  552. LLAvatarName avatar_name;
  553. if (LLAvatarNameCache::get(agent_id, &avatar_name))
  554. {
  555. // Always show "Display Name [Legacy Name]" for
  556. // security reasons
  557. name = avatar_name.getNames();
  558. }
  559. }
  560. args["NAME"] = name;
  561. }
  562. if (LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
  563. {
  564. gNotifications.add("GrantedModifyRights", args);
  565. }
  566. else
  567. {
  568. gNotifications.add("RevokedModifyRights", args);
  569. }
  570. }
  571. (mBuddyInfo[agent_id])->setRightsFrom(new_rights);
  572. }
  573. }
  574. addChangedMask(LLFriendObserver::POWERS, agent_id);
  575. notifyObservers();
  576. }
  577. void LLAvatarTracker::processChangeUserRights(LLMessageSystem* msg, void**)
  578. {
  579. LL_DEBUGS("AvatarTracker") << "called" << LL_ENDL;
  580. gAvatarTracker.processChange(msg);
  581. }
  582. //static
  583. void LLAvatarTracker::callbackLoadAvatarName(const LLUUID& id, bool online,
  584. const LLAvatarName& avatar_name)
  585. {
  586. std::string name;
  587. if (!LLAvatarName::sLegacyNamesForFriends &&
  588. LLAvatarNameCache::useDisplayNames())
  589. {
  590. if (LLAvatarNameCache::useDisplayNames() == 2)
  591. {
  592. name = avatar_name.mDisplayName;
  593. }
  594. else
  595. {
  596. name = avatar_name.getNames();
  597. }
  598. }
  599. else
  600. {
  601. name = avatar_name.getLegacyName();
  602. }
  603. // Popup a notify box with online status of this agent
  604. LLSD args;
  605. args["NAME"] = name;
  606. LLNotificationPtr n = gNotifications.add(online ? "FriendOnline"
  607. : "FriendOffline", args);
  608. // If there is an open IM session with this agent, send a notification
  609. // there too.
  610. LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, id);
  611. LLFloaterIMSession* floater = LLFloaterIMSession::findInstance(session_id);
  612. if (floater)
  613. {
  614. std::string mesg = n->getMessage();
  615. if (!mesg.empty())
  616. {
  617. floater->addHistoryLine(mesg,
  618. gSavedSettings.getColor4("SystemChatColor"));
  619. }
  620. }
  621. }
  622. void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
  623. {
  624. static LLCachedControl<bool> chat_notify(gSavedSettings,
  625. "ChatOnlineNotification");
  626. S32 count = msg->getNumberOfBlocksFast(_PREHASH_AgentBlock);
  627. LL_DEBUGS("AvatarTracker") << "Received " << count
  628. << " online notifications **** " << LL_ENDL;
  629. if (count <= 0)
  630. {
  631. return;
  632. }
  633. LLUUID tracking_id;
  634. if (mTrackingData)
  635. {
  636. tracking_id = mTrackingData->mAvatarID;
  637. }
  638. LLUUID agent_id;
  639. for (S32 i = 0; i < count; ++i)
  640. {
  641. msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_AgentID, agent_id, i);
  642. const LLRelationship* info = getBuddyInfo(agent_id);
  643. if (info)
  644. {
  645. setBuddyOnline(agent_id, online);
  646. if (chat_notify)
  647. {
  648. LLAvatarNameCache::get(agent_id,
  649. boost::bind(&callbackLoadAvatarName,
  650. _1, online, _2));
  651. }
  652. }
  653. else
  654. {
  655. llwarns << "Received online notification for unknown buddy: "
  656. << agent_id << " is "
  657. << (online ? "online" : "offline") << llendl;
  658. }
  659. if (tracking_id == agent_id)
  660. {
  661. // We were tracking someone who went offline
  662. deleteTrackingData();
  663. }
  664. addChangedMask(LLFriendObserver::ONLINE, agent_id);
  665. // *TODO: get actual inventory Id
  666. gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD,
  667. LLUUID::null);
  668. }
  669. gAvatarTracker.notifyObservers();
  670. gInventory.notifyObservers();
  671. }
  672. //static
  673. void LLAvatarTracker::formFriendship(const LLUUID& id)
  674. {
  675. if (id.notNull())
  676. {
  677. LLRelationship* buddy_info = get_ptr_in_map(gAvatarTracker.mBuddyInfo,
  678. id);
  679. if (!buddy_info)
  680. {
  681. // The default for relationship establishment is to have both
  682. // parties visible online to each other.
  683. buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,
  684. LLRelationship::GRANT_ONLINE_STATUS,
  685. false);
  686. gAvatarTracker.mBuddyInfo[id] = buddy_info;
  687. gAvatarTracker.addChangedMask(LLFriendObserver::ADD, id);
  688. gAvatarTracker.notifyObservers();
  689. }
  690. LLVOAvatar* avatarp = gObjectList.findAvatar(id);
  691. if (avatarp)
  692. {
  693. static LLCachedControl<LLColor4U> map_friend(gColors, "MapFriend");
  694. avatarp->setMinimapColor(LLColor4(map_friend));
  695. }
  696. }
  697. }
  698. //static
  699. bool LLAvatarTracker::isAgentFriend(const LLUUID& agent_id)
  700. {
  701. return gAvatarTracker.isBuddy(agent_id);
  702. }
  703. //static
  704. bool LLAvatarTracker::isAgentMappable(const LLUUID& agent_id)
  705. {
  706. const LLRelationship* buddy = gAvatarTracker.getBuddyInfo(agent_id);
  707. return buddy && buddy->isOnline() &&
  708. buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION);
  709. }
  710. //static
  711. void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**)
  712. {
  713. LLUUID id;
  714. msg->getUUID("ExBlock", "OtherID", id);
  715. if (id.isNull())
  716. {
  717. return;
  718. }
  719. LLRelationship* buddy = get_ptr_in_map(gAvatarTracker.mBuddyInfo, id);
  720. if (buddy)
  721. {
  722. gAvatarTracker.mBuddyInfo.erase(id);
  723. gAvatarTracker.addChangedMask(LLFriendObserver::REMOVE, id);
  724. delete buddy;
  725. gAvatarTracker.notifyObservers();
  726. }
  727. LLVOAvatar* avatarp = gObjectList.findAvatar(id);
  728. if (avatarp)
  729. {
  730. static LLCachedControl<LLColor4U> map_avatar(gColors, "MapAvatar");
  731. avatarp->setMinimapColor(LLColor4(map_avatar));
  732. }
  733. }
  734. void LLAvatarTracker::dirtyBuddies()
  735. {
  736. mModifyMask |= LLFriendObserver::REMOVE | LLFriendObserver::ADD;
  737. notifyObservers();
  738. }
  739. ///----------------------------------------------------------------------------
  740. /// Tracking Data
  741. ///----------------------------------------------------------------------------
  742. LLTrackingData::LLTrackingData(const LLUUID& avatar_id,
  743. const std::string& name)
  744. : mAvatarID(avatar_id),
  745. mHaveInfo(false),
  746. mHaveCoarseInfo(false)
  747. {
  748. mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY);
  749. mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
  750. mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
  751. if (!name.empty())
  752. {
  753. mName = name;
  754. }
  755. }
  756. void LLTrackingData::agentFound(const LLUUID& prey,
  757. const LLVector3d& estimated_global_pos)
  758. {
  759. if (prey != mAvatarID)
  760. {
  761. llwarns << "LLTrackingData::agentFound() - found " << prey
  762. << " but looking for " << mAvatarID << llendl;
  763. }
  764. mHaveInfo = true;
  765. mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
  766. mGlobalPositionEstimate = estimated_global_pos;
  767. }
  768. bool LLTrackingData::haveTrackingInfo()
  769. {
  770. LLVOAvatar* avatarp = gObjectList.findAvatar(mAvatarID);
  771. if (avatarp && !avatarp->isDead())
  772. {
  773. mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY);
  774. mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
  775. mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
  776. mHaveInfo = true;
  777. return true;
  778. }
  779. if (mHaveCoarseInfo &&
  780. !mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY))
  781. {
  782. // if we reach here, then we have a 'recent' coarse update
  783. mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
  784. mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
  785. return true;
  786. }
  787. if (mUpdateTimer.checkExpirationAndReset(FIND_FREQUENCY))
  788. {
  789. gAvatarTracker.findAgent();
  790. mHaveCoarseInfo = false;
  791. }
  792. if (mAgentGone.checkExpirationAndReset(OFFLINE_SECONDS))
  793. {
  794. mHaveInfo = false;
  795. mHaveCoarseInfo = false;
  796. }
  797. return mHaveInfo;
  798. }
  799. void LLTrackingData::setTrackedCoarseLocation(const LLVector3d& global_pos)
  800. {
  801. mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY);
  802. mGlobalPositionEstimate = global_pos;
  803. mHaveInfo = true;
  804. mHaveCoarseInfo = true;
  805. }
  806. ///----------------------------------------------------------------------------
  807. // various buddy functors
  808. ///----------------------------------------------------------------------------
  809. bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id,
  810. LLRelationship* buddy)
  811. {
  812. if (buddy->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS))
  813. {
  814. mProxy.emplace(buddy_id);
  815. }
  816. return true;
  817. }
  818. bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id,
  819. LLRelationship* buddy)
  820. {
  821. if (gCacheNamep)
  822. {
  823. gCacheNamep->getName(buddy_id, mFirst, mLast);
  824. }
  825. std::ostringstream fullname;
  826. fullname << mFirst << " " << mLast;
  827. buddy_map_t::value_type value(fullname.str(), buddy_id);
  828. if (buddy->isOnline() &&
  829. buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION))
  830. {
  831. mMappable.emplace(value);
  832. }
  833. return true;
  834. }
  835. bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id,
  836. LLRelationship* buddy)
  837. {
  838. if (gCacheNamep)
  839. {
  840. gCacheNamep->getName(buddy_id, mFirst, mLast);
  841. }
  842. std::ostringstream fullname;
  843. fullname << mFirst << " " << mLast;
  844. buddy_map_t::value_type value(fullname.str(), buddy_id);
  845. if (buddy->isOnline())
  846. {
  847. mOnline.emplace(value);
  848. }
  849. return true;
  850. }
  851. bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id,
  852. LLRelationship* buddy)
  853. {
  854. if (gCacheNamep)
  855. {
  856. gCacheNamep->getName(buddy_id, mFirst, mLast);
  857. }
  858. std::ostringstream fullname;
  859. fullname << mFirst << " " << mLast;
  860. buddy_map_t::value_type value(fullname.str(), buddy_id);
  861. if (buddy->isOnline())
  862. {
  863. mOnline.emplace(value);
  864. }
  865. else
  866. {
  867. mOffline.emplace(value);
  868. }
  869. return true;
  870. }